介绍:
在iOS中,两个常用的callback(回调)机制:
I delegate
II notification
delegate简单直接。用户注册自己为一个delegate,并实现它需要的delegate方法
[worker setDelegate:self]; - (void)workerDidFinish:(Worker *)sender { } - (void)worker:(Worker *)sender didFinishSubTask:(id)subtask inDuration:(NSTimeInterval)elapsed { } - (BOOL)worker:(Worker *)sender shouldPerformSubTask:(id)subtask { }notification也很简单,但是需要多一些的准备,用户必须注册,每一个它感兴趣的notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(workerDidFinish:) name:WorkerDidFinishNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(workerDidFinishSubTask:) name:WorkerDidFinishSubTaskNotification object:nil]; - (void)workerDidFinish:(NSNotification *)notification { Worker *sender = [notification object]; } - (void)workerDidFinishSubTask:(NSNotification *)notification { Worker *sender = [notification object]; id subtask = [[notification userInfo] objectForKey:@"subtask"]; NSTimeInterval elapsed = [[[notification userInfo] objectForKey"duration"] doubleValue]; }
从上面可以看出,我们必须从notification object中抽出参数。有时候,我们必须从字典类型的对象里抽取参数,前提是必须知道字典中的键值。
并且,第3个delegate方法是没法通过notification实现的,因为notification机制是不允许返回变量的。
每种机制都有优点和缺点。
Delegate的优点:
多个callback要更容易注册
多个参数,明显要容易使用的多
允许返回变量
Delegate的缺点:
只能有一个delegate
notification的优点:
多个object可以注册一个notification
notification的缺点:
注册多个callback很繁琐
特别烦,要抽取多个参数从字典对象中
当需要返回变量时候,无法实现
XMPPFramework需要什么???
1. xmpp framework必须能够对多个监听者广播事件
就比如一个简单的message,聊天窗口,历史记录,pop-up的通知都可能在监听
2. xmpp framework必须很易扩展
它应该能够支持大量的XEP‘s,同样还要能够支持协议开发人员的自定义实现。换句话说,在广播和监听都必须很简单
3. 系统必须支持变量返回
比如IQ(Info/Query,信息与查询)在处理mandate,如果一个用户收到了’get‘或者'set'类的消息,却不知道怎么处理,这是就一定需要返回'error',在多插件情况下,必须能够很好的执行
4. 保证线程安全
xmpp framework是大量的并行,套接字IO,xml解析,xmpp stanza routing,模型,硬盘的IO,还有delegate全都在他们自己的GCD队列上,在多核设备上意味着多任务在不同线程同时进行,系统不能让我们through hoops保证并发和稳定。
GCDMulticastDelegate应运而生!
它长什么样???
很简单,作为用户,只需要如下操作:
// Add myself as a delegate, and tell xmppStream to invoke my delegate methods on the main thread [xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; // Then just implement whatever delegate methods you need like normal - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message { ... }这就是所有,就跟传统的delegate模式一样,只是可以延伸到具体是哪个线程。
如果之后,你想把你的processing从main thread中移除,也很简单:
// Handle most stuff on the main thread [xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; // But do that one slow thing on a background queue so it doesn't slow down the UI anymore [xmppStream addDelegate:bgProcessor delegateQueue:bgProcessorQueue];
对于像iPhone这样的环境,是个非常好的方法,并不是为了创造新的paradigm而写的
我怎么使用自己的插件:
作为一个广播者,使用multicast delegate,应该如下声明和初始化:
GCDMulticastDelegate <MyPluginDelegate> *multicastDelegate; multicastDelegate = (GCDMulticastDelegate <MyPluginDelegate> *)[[GCDMulticastDelegate alloc] init];添加允许别人添加和删除他们到delegate list的方法:
- (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue { [multicastDelegate addDelegate:delegate delegateQueue:delegateQueue]; } - (void)removeDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue { [multicastDelegate removeDelegate:delegate delegateQueue:delegateQueue]; }
如果你想对所有注册的delegates调用方法,可以:
[multicastDelegate worker:self didFinishSubTask:subtask inDuration:elapsed];很简单,multicast delegate通知了所有的delegates,每个都在他们自己的dispatch_queue上,通过dispatch_async();