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原理差不多。谢谢。