对象去耦的方法之一:观察者模式

观察者模式是指一个对象状态发生改变,会通知正在对它进行观察的对象。观察者模式最常见的两种:KVO,NSNotification。

首先关于KVO:(这里注意KVO和KVC都基于runtime的动态机制)

观察者是在被观察者内进行注册的,同时观察者和被观察者都要实现NSKeyValueObserving协议(NSObject已默认实现)

例子:

 

被观察者:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.watcher = [TestWatche alloc];   //注册观察者(1) [self addObserver:self.watcher forKeyPath:@"state" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"pass content"]; self.state = @"launch"; return YES; } - (void)applicationDidEnterBackground:(UIApplication *)application { self.state = @"backgroud"; }

观察者:
#import "TestWatche.h"
@implementation TestWatche
//实现观察方法(2)
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    NSLog(@"state change:%@",change);
}
@end
//移除方法(3)
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

 

实现分析:

使用观察者模式需要被观察者的配合,当被观察者的状态发生变化的时候通过事先定义好的接口(协议)通知观察者。在KVO的使用中我们并不需要向被观察者添加额外的代码,就能在被观察的属性变化的时候得到通知,这个功能是如何实现的呢?同KVC一样依赖于强大的Runtime机制。

系统实现KVO有以下几个步骤:

  • 当类A的对象第一次被观察的时候,系统会在运行期动态创建类A的派生类。我们称为B。
  • 在派生类B中重写类A的setter方法,B类在被重写的setter方法中实现通知机制。
  • 类B重写会 class方法,将自己伪装成类A。类B还会重写dealloc方法释放资源。
  • 系统将所有指向类A对象的isa指针指向类B的对象。

KVO同KVC一样,通过 isa-swizzling 技术来实现。当观察者被注册为一个对象的属性的观察对象的isa指针被修改,指向一个中间类,而不是在真实的类。其结果是,isa指针的值并不一定反映实例的实际类。

所以不能依靠isa指针来确定对象是否是一个类的成员。应该使用class方法来确定对象实例的类。

 

关于Notification:

不同于KVO,这里观察者是在观察者内部自己注册的。

被观察者:
- (void)applicationDidEnterBackground:(UIApplication *)application { [[NSNotificationCenter defaultCenter]postNotificationName:@"APPTerminate" object:self]; }
观察者:
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    //注意此处的selector有参数,要加冒号
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(doSomething:) name:@"APPTerminate" object:nil];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    [[NSNotificationCenter defaultCenter]removeObserver:self];
    // Dispose of any resources that can be recreated.
}

#pragma mark -处理通知
-(void)doSomething:(NSNotification*)notification{
    NSLog(@"收到通知");
}
@end
 

 引用:

http://www.cnblogs.com/zy1987/p/4616764.html

https://segmentfault.com/a/1190000000768605

posted @ 2017-03-17 17:01  encoreMiao  阅读(339)  评论(0编辑  收藏  举报