iOS-观察者模式
何为观察者模式,也就是说当被观察者发生了改变要观察者知道,并作出相应的处理。本文先使用系统的,之后实现观察者模式来了解其真正原理。
目录:
1.系统观察者模式的使用
2.自定义观察者模式
下面我们来分解iOS编程中的观察模式的使用:
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
该方法是NSObject的一个扩展类目,通过它我们可以给对象添加观察者observer,观察者并不是关心被观察者的所用动态,它只是关心被观察者的一些特性的改变而已所以通过keyPath来指定,当keyPath改变了,你可以把它改变了什么东西通知给观察者,通过option来指定,还可以设置任意类型的上下文context。观察者所要做的内容是做出相应的改变。
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
这个也是NSOject的一个扩展类目,当被观察者的某个特性改变了,观察者如果对该特性观察了就会调用改函数
下面我们来使用系统提供的观察者模式:通过函数调用跟踪日志
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @property (nonatomic,assign)int observeredAttr; @end
@interface ViewController () @end //函数调用跟踪静态变量 static int traceInt = 0; @implementation ViewController{ } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSLog(@"%d ------ %s",traceInt++,__func__); [self addObserver:self forKeyPath:@"observeredAttr" options:0 context:nil]; //改变观察变量的值,这样它会出发观察者的操作 [self changeObserverdAttr]; } -(void)changeObserverdAttr{ NSLog(@"%d ------ %s",traceInt++,__func__); self.observeredAttr = 100; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ NSLog(@"%d ------ %s",traceInt++,__func__); }
2015-04-02 21:03:06.366observer[928:30124] 0 ------ -[ViewController viewDidLoad]
2015-04-02 21:03:06.367observer [928:30124] 1 ------ -[ViewController changeObserverdAttr]
2015-04-02 21:03:06.367 observer[928:30124] 2 ------ -[ViewController observeValueForKeyPath:ofObject:change:context:]
重结果中可以看出来,添加观察者,这里设置为自己,改变被观察的属性,调用被观察的方法。
自定义观察者模式:
被观察者的设计:
头文件:
#import <Foundation/Foundation.h> @interface ObserveredObject : NSObject @property (nonatomic,assign)int observeredAttr; //被观察的属性 //把观察者添加到列表中 -(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath; @end
#import "ObserveredObject.h" #import "ObserverObject.h" @implementation ObserveredObject { //观察者队列字典 NSMutableDictionary *_oberverQueue; } -(instancetype)init{ if (self= [super init]) { _oberverQueue = [[NSMutableDictionary alloc]init]; } return self; } //把观察者放到观察者字典中通过path来作为值,observer作为对象 -(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath{ NSLog(@"------ %s",__func__); [_oberverQueue setObject:observer forKey:keyPath]; } //重写属性的set方法 -(void)setObserveredAttr:(int)observeredAttr{ NSLog(@"------ %s",__func__); if (observeredAttr !=_observeredAttr) { NSArray *allKey = [_oberverQueue allKeys]; for (int i= 0; i<allKey.count; i++) { if ([allKey[i] isEqualToString:@"observeredAttr"]) { ObserverObject *observer = [_oberverQueue objectForKey:@"observeredAttr"]; [observer changedActionForPath:@"observeredAttr" andChangValue:[NSString stringWithFormat:@"%d",observeredAttr]]; } } } } @end
头文件:
#import <Foundation/Foundation.h> @interface ObserverObject : NSObject //当观察的属性改变时掉用该方法 -(void)changedActionForPath:(NSString *)path andChangValue:(id)value; @end
@implementation ObserverObject -(void)changedActionForPath:(NSString *)path andChangValue:(id)value{ NSLog(@"------ %s",__func__); if ([path isEqualToString:@"observeredAttr"]) { NSLog(@"你观察的对象的observeredAttr已经改变了%@",value); } } @end
NSLog(@"------ %s",__func__); //初始化被观察者 ObserveredObject *ed = [[ObserveredObject alloc]init]; //在没有添加观察者的时候初始化属性 ed.observeredAttr = 50; //初始化观察者 ObserverObject *ob = [[ObserverObject alloc]init]; //为ed添加一个观察者,观察的属性为observeredAttr [ed addObserver:ob forKeyPath:@"observeredAttr"]; //改变被观察者的属性的值 ed.observeredAttr = 100;
运行结果:
2015-04-02 21:34:23.933 Target_action[1199:43513] ------ -[ViewController viewDidLoad]
2015-04-02 21:34:23.933 Target_action[1199:43513] ------ -[ObserveredObject setObserveredAttr:]
2015-04-02 21:34:23.933 Target_action[1199:43513] ------ -[ObserveredObject addObserver:forKeyPath:]
2015-04-02 21:34:23.933 Target_action[1199:43513] ------ -[ObserveredObject setObserveredAttr:]
2015-04-02 21:34:23.933 Target_action[1199:43513] ------ -[ObserverObject changedActionForPath:andChangValue:]
2015-04-02 21:34:23.933 Target_action[1199:43513] 你观察的对象的observeredAttr已经改变了100
小结:
使用系统自带的观察者模式要使用self.property的方法否则不会调用观察者的观察方法,系统的self.property的设计原理和上面自定义的setMethod原理差不多。谢谢。
原文地址:http://blog.csdn.net/fanyiyao980404514/article/details/44836913