iOS 中KVC、KVO、NSNotification、delegate 总结及区别

2020-01-18 16:56:47刘景俊

      3.取消注册观察removeObserver:forKeyPath:context:

Demo:


@interface myPerson : NSObject 
{ 
  NSString *_name; 
  int   _age; 
  int   _height; 
  int   _weight; 
} 
@end 
 
@interface testViewController : UIViewController 
@property (nonatomic, retain) myPerson *testPerson; 
 
- (IBAction)onBtnTest:(id)sender; 
@end 
 
- (void)testKVO 
{ 
  testPerson = [[myPerson alloc] init]; 
   
  [testPerson addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew context:nil]; 
} 
 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
  if ([keyPath isEqualToString:@"height"]) { 
    NSLog(@"Height is changed! new=%@", [change valueForKey:NSKeyValueChangeNewKey]); 
  } else { 
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
  } 
} 
 
- (IBAction)onBtnTest:(id)sender { 
  int h = [[testPerson valueForKey:@"height"] intValue];   
  [testPerson setValue:[NSNumber numberWithInt:h+1] forKey:@"height"]; 
  NSLog(@"person height=%@", [testPerson valueForKey:@"height"]); 
} 
 
- (void)dealloc 
{ 
  [testPerson removeObserver:self forKeyPath:@"height" context:nil]; 
  [super dealloc]; 
} 

第一段代码声明了myPerson类,里面有个_height的属性。在testViewController有一个testPerson的对象指针。

      在testKVO这个方法里面,我们注册了testPerson这个对象height属性的观察,这样当testPerson的height属性变化时, 会得到通知。在这个方法中还通过NSKeyValueObservingOptionNew这个参数要求把新值在dictionary中传递过来。

      重写了observeValueForKeyPath:ofObject:change:context:方法,这个方法里的change这个NSDictionary对象包含了相应的值。

      需要强调的是KVO的回调要被调用,属性必须是通过KVC的方法来修改的,如果是调用类的其他方法来修改属性,这个观察者是不会得到通知的。

3、NSNotification的用法见http://www.easck.com/eduora_meimei/article/details/44198909

区别:

delegate 的 优势 :

     1.非常严格的语法。所有将听到的事件必须是在delegate协议中有清晰的定义。

     2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误

     3.协议必须在controller的作用域范围内定义

      4.在一个应用中的控制流程是可跟踪的并且是可识别的;

     5.在一个控制器中可以定义定义多个不同的协议,每个协议有不同的delegates

     6.没有第三方对象要求保持/监视通信过程。