[object addObserver:observer forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:nil];
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if([keyPath isEqualToString:@"text"]) { NSLog(@"text:@%@", change[NSKeyValueChangeNewKey]); } }
[object removeObserver:self forKeyPath:@"text"];
这里有几个问题
下面我们将针对这几个问题进行封装
@interface XYObserver : NSObject @end @interface XYObserver () @property (nonatomic, assign) XYObserverType type; // 观察者的类型 @property (nonatomic, weak) id target; // 被观察的对象的值改变时后的响应方法所在的对象 @property (nonatomic, assign) SEL selector; // 被观察的对象的值改变时后的响应方法 @property (nonatomic, copy) XYObserver_block_sourceObject_new_old block; // 值改变时执行的block @property (nonatomic, assign) id sourceObject; // 被观察的对象 @property (nonatomic, strong) NSString *keyPath; // 被观察的对象的keyPath -(instancetype) initWithSourceObject:(id)sourceObject keyPath:(NSString*)keyPath target:(id)target selector:(SEL)selector type:(XYObserverType)type; -(instancetype) initWithSourceObject:(id)sourceObject keyPath:(NSString*)keyPath block:(XYObserver_block_sourceObject_new_old)block; @end
@interface NSObject (XYObserver) @property (nonatomic, readonly, strong) NSMutableDictionary *observers; /** * api parameters 说明 * * sourceObject 被观察的对象 * keyPath 被观察的属性keypath * target 默认是self * selector @selector(propertyNew:) @selector(propertyNew:old:) @selector(propertyIn:new:) @selector(propertyIn:new:old:) * type 根据selector自动赋值 * block selector, block二选一 */ -(void) observeWithObject:(id)sourceObject property:(NSString*)property; -(void) observeWithObject:(id)sourceObject property:(NSString*)property block:(XYObserver_block_sourceObject_new_old)block; -(void) removeObserverWithObject:(id)sourceObject property:(NSString *)property; -(void) removeObserverWithObject:(id)sourceObject; -(void) removeAllObserver; @end
-(void) observeWithObject:(id)object property:(NSString*)property{ SEL aSel = NSSelectorFromString([NSString stringWithFormat:@"%@New:", property]); if ([self respondsToSelector:aSel]) { [self observeWithObject:object keyPath:property target:self selector:aSel type:XYObserverType_new]; return; } . . . }
-(void) observeWithObject:(id)object property:(NSString*)property block:(XYObserver_block_sourceObject_new_old)block{ [self observeWithObject:object keyPath:property block:block]; }
-(void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context { __weak __typeof(self) weakSelf = self; if (_block) { _block(weakSelf, change[NSKeyValueChangeNewKey], change[NSKeyValueChangeOldKey]); return; } if (_type == XYObserverType_new) { action(_target, _selector, change[NSKeyValueChangeNewKey]); }else if (_type == XYObserverType_new_old) { action(_target, _selector, change[NSKeyValueChangeNewKey], change[NSKeyValueChangeOldKey]); }else if (_type == XYObserverType_self_new) { action(_target, _selector, self, change[NSKeyValueChangeNewKey]); }else if (_type == XYObserverType_self_new_old) { action(_target, _selector, self, change[NSKeyValueChangeNewKey], change[NSKeyValueChangeOldKey]); } }
-(void) observeWithObject:(id)object keyPath:(NSString*)keyPath target:(id)target selector:(SEL)selector type:(XYObserverType)type{
XYObserver *ob = [[XYObserver alloc] initWithSourceObject:object keyPath:keyPath target:target selector:selector type:type];
NSString *key = [NSString stringWithFormat:@"%@_%@", object, keyPath];
[self.observers setObject:ob forKey:key];
}
-(void) observeWithObject:(id)object property:(NSString*)property block:(XYObserver_block_sourceObject_new_old)block{
[self observeWithObject:object keyPath:property block:block];
}
-(id) observers{
id object = objc_getAssociatedObject(self, NSObject_observers);
if (nil == object) {
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:8];
objc_setAssociatedObject(self, NSObject_observers, dic, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return dic;
}
return object;
}
-(void) dealloc { if (_sourceObject) { [_sourceObject removeObserver:self forKeyPath:_keyPath]; } }
#define ON_KVO_1_( __property ) -(void) __property##New:(id)newValue #define ON_KVO_2_( __property ) -(void) __property##New:(id)newValue old:(id)oldValue #define ON_KVO_3_( __property ) -(void) __property##In:(id)sourceObject new:(id)newValue #define ON_KVO_4_( __property ) -(void) __property##In:(id)sourceObject new:(id)newValue old:(id)oldValue
[self observeWithObject:self property:@"testKVO"]; ON_KVO_4_(testKVO){ NSLogD(@"obj:%@ new:%@ old:%@", sourceObject, newValue, oldValue); } [self observeWithObject:self property:@"testKVO2" block:^(id sourceObject, id newValue, id oldValue) { NSLogD(@"obj:%@ new:%@ old:%@", sourceObject, newValue, oldValue); }];
这个封装的优点是在使用KVO的时候不需要记住太多东西..
代码可以在https://github.com/uxyheaven/XYQuickDevelop下载到