利用NSNotificationCenter构建异步系统的问题
背景:
1)IOS消息应用
2)系统从整体上从上到下依次分为三个层次:UI层、模型层、通讯层。
3)上层对下层依赖,下层对上层一无所知。
4)UI层对模型层的调用,模型层对通讯层的调用,均采用异步方式。
5)异步操作回调机制准备利用NSNotificationCenter
举例:
UI层一个对象调用模型层的一个对象的方法,调用后立即返回,等模型层有了结果之后,回调UI层的相关方法,具体步骤如下:
1)UI层对象o1调用模型层对象o2的异步方法c2,调用时将调用者自身o1与回调函数c1作为参数传入
2)模型层对象首先为此操作生成一个唯一的ID,并将此ID作为事件name,把o1,c1注册到NSNotificationCenter
3)模型层o2调用通讯层的相关方法,机制与UI调用模型相同,此处省略。
4)模型层o2收到操作结果后,通过NSNotificationCenter和操作ID来通知UI层的对象o1执行c1。
5)将此次通知从NSNotificationCenter中注销,因为本次操作已经结束。
问题是:
1)由模型层的对象帮UI层的对象在NSNotificationCenter注册通知是可以实现的,但调用通知后,还要帮UI层对象注销通知,这个不知道怎么实现,因为注销通知也需要传入通知对象,模型层此时并没有UI层的对象。
2)这种异步调用的机制设计的是否合理?
3)若此机制设计的合理,那么利用NSNotificationCenter是否合理?
Answers
上次写时忘了说一个细节,通知得在主线程,加入你用了通知模式注意这个问题。
你这应该属于是 模型-视图-控制器(通知+通讯)MVC 模式。
视图不应该直接去操作模型。
在控制器也就是你说的通讯层去定义通知相关的操作。
下面写的通知模块也属于控制器,包括通讯也属于。
1,步骤应该是,view上先有操作,到控制器层去
1,通讯开始,add notification
2,通讯结束,返回消息,post notification
3,收到通知,执行操作并 remove observer
自定义YourNotification
//所需数据 id object; id observer; SEL selector;
自定义YourNotificationCenter,单例类
//通过key value存放你的notificationName和observer NSMutableDictionary *observers; //你的单例中心,如何写单例有不少教程 static YourNotificationCenter *yourNotificationCenter; //异步队列,当然你也可以不需要这个,直接通过线程delay去做 NSNotificationQueue *queue;
需要实现的方法和YourNotificationCenter中类似,根据你的需求,主要需要的是
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject; - (void)postNotification:(NSNotification *)notification; - (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo; - (void)removeObserver:(id)observer; - (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
当你UI层有改变时,通过控制器去添加Notification。关键操作在于这个Notificaiton的userInfo字典,这个字典可以包含你想包含的任何信息,也就是说在响应通知的时候你可以把object的任何信息放入userInfo中。结束后可以调用你控制器中所写的删除监控器的方法,将其remove。
然后回答你的三个问题,
1,通过userInfo去传递object,name。
2,异步调用的话,你这边增加了模型和视图的耦合,需要增加控制器层去操作。
3,如我上述描述,NSNotificationCenter本身一个观察者模式,包括观察者注册、通知及删除等,基于kvo机制,去自定义YourNotification,YourNotificationCenter等来关联你的model和view。
以上只是说如何通过notification去搭建框架。
属我拙见,既然有通讯层,封装一套异步请求操作不就完事了。