iOS - 观察者模式与四种实现

来源:互联网 发布:手机数据自动开启 编辑:程序博客网 时间:2024/06/05 10:43

1. 了解什么是观察者模式

2. iOS中观察者模式应用

 

什么是观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

 

 一个典型的例子是订阅报纸。你不用去任何地方,只需要将你的个人地址信息以及订阅信息告诉出版社,出版社就知道如何将相关报纸传递给你。这种模式的第二个名称叫做发布/订阅模式。

 

观察者模式的的思想非常简单,Subject(主题)允许别的对象——观察者(这些对象实现了观察者接口)对这个Subject的改变进行订阅和取消订阅。当Subject发生了变化——那么Subject会将这个变化发送给所有的观察者,观察者就能对Subject的变化做出更新 。

 

简单的说就是,当某对象改变时,自动通知所有相关的状态进行更新。

 

 

iOS中观察者模式

在iOS中观察者模式的实现有四种方法:NSNotification、KVO、Protocol以及Code Block代码块。

都是很基本的技术,直接上重点,

 

要点:

  1. Notification是一对多的,而delegate回调是一对一的。但是你可以做一个Array来实现对多回调,这个问题的其实意义不大。
  2. Notification - NotificationCenter机制使用了操作系统的对象间通讯功能,而delegate是直接的函数调用。Notification跨度大,而delegate效率可能比较高。
  3. 相较于前两者KVO才是一种真正的观察者模式,它允许你将一个处理函数绑定到某个类的属性,属性发生改变是就会自动触发,不像其他两种需要你手动的发通知。KVO是一种非常灵活的观察机制,广泛应用于界面设计。KVO在另一文中会有介绍。
  4. Code Block其实就相当于C的函数指针,可以用来做各种回调。我觉得其应当具备最高的效率。使用Code Block要注意的地方就是使用外部变量。在block里直接引用外部变量的话会在block定义的时候复制外部变量的一个拷贝,也就是说得到的是block定义时的值,在block内修改这个值也不会传给外部。要得到实时的数据,或者将数据传出的话需要在相关变量前面加__block即可。

 

 

1. Notification

NotificationCenter机制使用了操作系统的对象间通讯功能,发布消息的方法如下所示:

1.NSNotification * broadcastMessage = [ NSNotification  notificationWithName:AnyNotification  object: Self ];

2.NSNotificationCenter * notificationCenter = [ NSNotificationCenter  defaultCenter];

3.[NotificationCenterpostNotification: broadCastMessage];

 

要订阅感兴趣的对象中的相关事件,可以按照如下方法进行:

1.NSNotificationCenter * notificationCenter = [ NSNotificationCenter  defaultCenter];

2.[NotificationCenteraddObserver: Self  selector: @ selector (update:) name:AnyNotification  object: nil ];

 

回调代码:

-(void)update:(NSNotification*) notification

}

 

2. KVO

Key-ValueObserving Programming,通过KVO,某个对象中的特定属性发生了改变,别的对象可以获得通知。

[kvoSubjaddObserver:kvoObserver forKeyPath:"changeableProperty" options:NSKeyValueObservingOptionNewcontext:nil];

 

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)objectchange:(NSDictionary *)change context:(void *)context;

 

[kvoSubjremoveObserver:kvoObserver forKeyPath:@"changeableProperty"];

 

3. protocol/delegate

 

相当于其他语言的接口,不过OC中interface被占了,只能叫protocol。一般来说一个protocol至少有一个做事的函数和一个setDelegate的函数。

 

一个协议可以扩展自另一个协议,一个类可以有多个协议,可以通过关键字进行@required和@optional进行设置,如果不设置则默认是@required。

 

例子如下:

//定义一个协议
@protocolAnimalDelegate <NSObject>

@required //必须实现的方法
-(void)eat;

-(void)setDelegate:id<AnimalDelegate> delegate;

 

@optional //可选实现的方法
-(void)run;
-(void)say;
-(void)sleep;

@end

 

实现该协议

@interface Person: NSObject<AnimalDelegate>

{

id<AnimalDelegate> del;

}

-(void)eat;

-(void)setDelegate:id<AnimalDelegate> delegate;

@end

 

#import "Person.h"

@implementation Person

-(void)eat{
    NSLog(@"eating...");
}

-(void)setDelegate:id<AnimalDelegate> delegate

{
   self->del = delegate;
}

 

@end

 

 

4. Code Block

代码块,其实现类似于C的函数指针,可以用来做各种回调。但实际使用上更像C#中的匿名委托或者lambda表达式,可以将一个操作作为一个参数进行传递。

 

简单定义一个代码块:

void (^printBlock)(NSString *x);    

printBlock = ^(NSString* str)    

{    

    NSLog(@"print:%@", str);    

};    

printBlock(@"hello world!");    

 

但实际使用更多的是用在函数里,定义像这样:

-(void)doWork:(int(^)(int))predicate {  

 } 

 

调用:

 [selfdoWork:^(int a){

// do something

}];

0 0
原创粉丝点击