iOS-Developer-OCiOS - Developer - OC 进阶大全

Object-C中KVO探索

2019-08-01  本文已影响15人  zwwuchn

什么是KVO

KVO(Key-Value Observing),俗称键值监听。它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。

监听方法

- (void)addObserver:(NSObject*)observer forKeyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context;

移除监听

- (void)removeObserver:(NSObject*)anObserver forKeyPath:(NSString*)keyPath;

- (void)removeObserver:(NSObject*)observer forKeyPath:(NSString*)keyPath context:(void*)context;

回调监听

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context;

KVO使用步骤

  1. 注册,指定被观察者的属性
  2. 实现回调方法
  3. 移除观察

代码展示

@interfacePerson:NSObject

@property(nonatomic,assign)NSIntegerage;

@end

@implementationPerson

@end
self.person1 = [[Person alloc]init];

self.person2 = [[Person alloc]init];

NSLog(@"监听前%@ --- %@",object_getClass(self.person1),object_getClass(self.person2));

NSKeyValueObservingOptionsoptions =NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld;

[self.person2 addObserver:selfforKeyPath:@"age"options:options context:nil];

self.person2.age =20;

NSLog(@"监听后%@ --- %@",object_getClass(self.person1),object_getClass(self.person2));


[self.person2 removeObserver:selfforKeyPath:@"age"];

打印结果:

KVODemo[2879:697131] 监听前Person --- Person

KVODemo[2879:697131] 监听后NSKVONotifying_Person--- Person

监听前

监听后

RuntimeAPI动态生成一个NSKVONotifying_Person,并且让instance对象的isa指向这个全新的NSKVONotifying_Person

打印NSKVONotifying_Person内部方法

我们需要用到这个分类DLIntrospection已经有大神帮我们封装好了

+ (NSArray*)classes;

+ (NSArray*)properties;

+ (NSArray*)instanceVariables;

+ (NSArray*)classMethods;

+ (NSArray*)instanceMethods;

+ (NSArray*)protocols;

+ (NSDictionary*)descriptionForProtocol:(Protocol *)proto;

+ (NSString*)parentClassHierarchy;

断点调试结果

KVO[23897:840022] 监听前Person --- Person

(lldb) po [object_getClass(self.person1) instanceMethods]

<__NSArrayI0x604000429720>(

- (void)setAge:(q)arg0 ,

- (q)age

)

(lldb) po [object_getClass(self.person2) instanceMethods]

<__NSArrayI0x600000245ca0>(

- (void)setAge:(q)arg0 ,

- (class)class,

- (void)dealloc,

- (BOOL)_isKVOA

)

KVO[23897:840022] 监听后Person ---NSKVONotifying_Person

(lldb) po [object_getClass(self.person1) instanceMethods]

<__NSArrayI0x60000022a560>(

- (void)setAge:(q)arg0 ,

- (q)age

)

(lldb) po [object_getClass(self.person2) instanceMethods]

<__NSArrayI0x6040002217a0>(

- (void)setAge:(q)arg0 ,

- (q)age

)

结论

我们来证明一下

@implementationPerson

- (void)willChangeValueForKey:(NSString*)key {

NSLog(@"%@",NSStringFromSelector(_cmd));

[superwillChangeValueForKey:key];

}

- (void)didChangeValueForKey:(NSString*)key {

NSLog(@"begin---%@",NSStringFromSelector(_cmd));

[superdidChangeValueForKey:key];

NSLog(@"end---%@",NSStringFromSelector(_cmd));

}

@end
KVO[24586:884853] willChangeValueForKey:

KVO[24586:884853] begin---didChangeValueForKey:

KVO[24586:884853] {

kind =1;

new =20;

old =0;

}

KVO[24586:884853] end---didChangeValueForKey:



上一篇下一篇

猜你喜欢

热点阅读