观察者模式是指一个对象状态发生改变,会通知正在对它进行观察的对象。观察者模式最常见的两种: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