Block-KVO vs THObserversAndBinders vs KVOController。
每种的优点和缺点是什么?哪一个更好,为什么?
更新:最后,我倾向于使用Objective-Chain来处理KVO。 ReactiveCocoa也是一个选项,但可能过于宽泛。
答案 0 :(得分:12)
首先,我要说的是,这是一个主观问题的一个主要例子,可能不应该被问到here - 你在这里显然是一个很好的成员而且我是确定你已经知道了。
但是既然你问过,我会尝试尽可能不客观地回答你的主观问题 - 虽然它不是Stack Overflow的最佳问题,但总的来说这是一个很好的问题,而且我'我相信一些Google员工最终会在这里找到一个主观与否的答案!
首先,如果您对KVO
的唯一/主要投诉是语法(正如您在问题评论中提到的那样),那么不要去找{{ 3}}或其灵感,Objective-Chain。虽然它们具有令人难以置信的ReactiveCocoa量,但仅仅为了更容易理解的KVO
语法,它们的重量和复杂性都不值得。
在你提到的三个库中,弹出最多的是usefulness - 在直截了当的语法和关于线程安全的前期之间,你可以让大量的GitHub明星为自己说话。 这是我最初发布的三个选项的推荐。
其他选项,看起来也很轻巧,语法很棒,也有自己的优点 - KVOController是三者中唯一可以选择MIT许可证而不是BSD的选项,所以如果这样做&#39 ;为了你的项目需要优先考虑,并牢记这一点 - Block-KVO,尽管自2013年底以来没有更新,但它具有出色的文档和缺乏Facebook所有权,如果这也是你的事情。< / p>
希望这应该给你一个客观的清单,以帮助你选择最好的选择 - 并确保下次不那么开放:)
答案 1 :(得分:4)
这是一个最小的工作理念(我也被KVO风格推迟)。我们的想法是在KVO上下文中携带块,然后在触发观察时调用它。
// NSObject+KVOBlock.h
#import <Foundation/Foundation.h>
@interface NSObject (KVOBlock)
// invoke the block when the receiver's value at keyPath changes
// block params are the receiver, the keyPath and the old value
- (void)observeKeyPath:(NSString *)keyPath withBlock:(void (^)(id, NSString *, id))block;
- (void)unobserveKeyPath:(NSString *)keyPath;
@end
// NSObject+KVOBlock.m
#import "NSObject+KVOBlock.h"
@implementation NSObject (KVOBlock)
- (void)observeKeyPath:(NSString *)keyPath withBlock:(void (^)(id, NSString *, id))block {
[self addObserver:self forKeyPath:keyPath
options:NSKeyValueObservingOptionOld
context:(__bridge void *)(block)];
}
- (void)unobserveKeyPath:(NSString *)keyPath {
[self removeObserver:self forKeyPath:keyPath];
}
- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {
void (^block)(id, NSString *, id) = (__bridge void (^)(id, NSString *, id))context;
block(self, keyPath, [change objectForKey:NSKeyValueChangeOldKey]);
}
@end
这样称呼它......
// assume a class called SomeObject with an instance called someObject
someObject.someProperty = @"Bar";
[someObject observeKeyPath:@"someProperty" withBlock:^(SomeObject *object, NSString *keyPath, NSString *oldValue) {
// avoid referring directly to 'someObject' in this block, since it retains
// the block via the kvo context, thereby causing a retain cycle. The first
// param ('object') is exactly equal to someObject. So use that instead.
NSLog(@"object=%@, keyPath=%@, oldValue=%@, newValue=%@",
object, keyPath, oldValue, object.someProperty);
}];
// at any point after this, when you change someProperty, the block will be invoked
self.object.someProperty = @"Foo";
我使用上面的代码进行了一次小测试,并确认它至少在此处显示的情况下有效。控制台输出看起来像这样......
<SomeObject :0xblahblah>, keyPath=someProperty, oldValue=Bar, newValue=Foo