Notification:关于MVC模型中的'radio station'

转载请注明来源,谢谢——by Guava

Notification 既iOS中的“通知”站(广播站)机制可以用来监听系统、模型的变化。

也有书把这个模式称为监视模式。下文中,广播=通知,收听=监视。大家自行理解~

如果说,NSNotification是iOS中的广播站的话,NSNotification则相当于一个个广播出去的消息。

NSNotification的定义如下。

其中name指通知的名字;object为通知的poster(通知的发送者);userInfo是传送的消息,是一个NSDictionary类。

@interface NSNotification : NSObject <NSCopying, NSCoding>

@property (readonly, copy) NSString *name;
@property (nullable, readonly, retain) id object;
@property (nullable, readonly, copy) NSDictionary *userInfo;

- (instancetype)initWithName:(NSString *)name object:(nullable id)object userInfo:(nullable NSDictionary *)userInfo NS_AVAILABLE(10_6, 4_0) NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

@end

接收端:

通过

[NSNotificationCenter defaultCenter]

获得一个共享实例,就用这个对象来接收广播。

收听广播的方法是,向对象发送消息:

- (void)addObserver:(id)observer // you (the object to get notified) 收听广播的对象,对一般的controller来说是self。
           selector:(SEL)aSelector // a mothod inside of the observer . 收听的对象中的某个方法。当广播出现时调用这个方法。
               name:(nullable NSString *)aName //name of station.
             object:(nullable id)anObject;// whose changes you're interested in (nil is anyone's) 这个选项是nil的时候,可以收听来自任何对象的广播,当有值的时候,只收听来自该对象的广播。一般来说,设置成nil。

接下来是,我们有可能感兴趣(真正感兴趣的往往不是值的传递,而是是否发生了广播)的地方,是广播中传递了什么值,或者说,怎么获得广播中传递的值,以下是如果出现广播时,被调用到的方法:

- (void)aSelector:(NSNotification *) notification//这个方法的名字,应该和上面消息中传入的selector 的名字的一样的。
{
    notification.name; //the name passed about. 广播站的名称,和上面消息中传递的name的值是一样的。
    notification.object; //the object sending you notification. 发送广播的对象,对应着上面的sender。
    notification.userInfo; //notification-specific information about what happened. 包含的内容取决于发送广播的对象在里面存了什么内容
}

notification.userInfo实际上是一个NSDictionary,取数据的时候,还是需要用[notification.userInfo objectForKey:keyName]来取的。

如果不知道里面放着什么(也许是一个id类),也许会需要isKindOfClass或者respondsToSelector来使用它。

 

 

接收方最后一步处理,是关于把自己移除出广播机制的问题。在比较早先的版本,指向observer的指针是一个不安全保留型(unsafe retain),详情可见

斯坦福白胡子老爷爷的iOS系列讲解第5集

这个视频的57--60分钟。

或者文字版的:  Notification(一) 系统通知的监听移除 -- bao9107

然而这个指针的问题在现在(2015.10)已经得到了解决。

关于这个问题的测试,可以从 我的github 上把用例clone下来自己试试,证实的方式在上面也有写。

至于解决的方式,应该是依照白胡子老爷爷的想法,将该指针变成了一个weak的指针(个人推测)。

测试的结果是,当页面从堆里面释放之后,发送广播,没有反应,应用也没有崩溃。这显然是一个大家都想看到的结果(偷懒的没有写remove也不会造成应用崩溃了)。

移除监视者的方法有2种:

1.把对象从收听列表中剔除(取消收听所有的广播)

- (void)removeObserver:(id)observer;

2.移除对象对特定广播的收听. 其中,observer是收听者,aName是广播名称,anobject是发送者(poster)

- (void)removeObserver:(id)observer
                  name:(nullable NSString *)aName
                object:(nullable id)anObject;

 

发送端:

有下面3中方式可以产生一个广播

1. 使用一个NSNotification对象作为参数创建广播。(创建NSNotification方法不再赘述,官方提供了很多种创建的方式。)

- (void)postNotification:(NSNotification *)notification;

2 和 3 可以理解成,先创建了NSNotification,然后再执行了1方法。分别是:

- (void)postNotificationName:(NSString *)aName object:(nullable id)anObject;
- (void)postNotificationName:(NSString *)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;

 

 有任何意见或者疑问欢迎评论交流。

 

资料参考:

 斯坦福大学公开课:iOS 7应用开发

《疯狂iOS讲义(下)》--李刚

 

posted @ 2015-10-15 15:19  Guava_kingfeng  阅读(238)  评论(0编辑  收藏  举报