通知(NSNotification),是iOS开发中一种重要的设计模式,它的实质是程序内部提供的一种广播机制。把接受到的消息根据内部消息转发表,将消息转发给需要的对象。通知这种设计模式,在开发中常用来不同类之间的通信,也就是常说的页面之间的传值。
下面我们来看下相关的类:
NSNotification
这个类是通知类,由这个类创建的对象是一个通知对象,也可以理解为是一个消息对象。类中有三个成员变量:
/** name:是消息对象的唯一标识,接受通知消息时用来辨别 */
@property (readonly,copy)NSNotificationName name;
/** object:一个对象,可以理解为针对某个对象的消息 */
@property (nullable,readonly,retain)id object;
/** userInfo:一个字典,用来传值 */
@property (nullable,readonly,copy)NSDictionary *userInfo;
初始化:
//对象方法初始化一个通知对象,并给通知对象的属性赋值
- (instancetype)initWithName:(NSNotificationName)name object:(nullable id)object userInfo:(nullable NSDictionary *)userInfo API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) NS_DESIGNATED_INITIALIZER;
//类方法创建一个通知对象,这个方法没有userInfo这个属性的初始赋值,所以用来发送无传值的通知
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullable id)anObject;
//类方法初始化一个通知对象,并给通知对象的属性赋值
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;
注:NSNotification不可以使用init进行初始化。
NSNotificationCenter
这个类是通知中心类,内部实现是单利模式,每个程序都有一个默认的通知中心,用来调度通知的发送和接受。通知中心的特点:1:同步执行;2: 一对多发送消息;3: 降低程序耦合度。通知中心类相关方法:
接收通知的方法:
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSString *)aName object:(nullable id)anObject;
- (id <NSObject>)addObserverForName:(nullable NSString *)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue;
第一个方法使用的方式是最多的,第二个方法很少见到使用。第二个方法是支持block回调的,而queue参数就是在哪个队列。
发送通知的方法:
//发送通知,参数是一个通知对象
- (void)postNotification:(NSNotification *)notification;
//发送通知,参数是通知的名称,指定的对象
- (void)postNotificationName:(NSString *)aName object:(nullable id)anObject;
//发送通知,参数是通知的名称,指定的对象和传递的参数
- (void)postNotificationName:(NSString *)aName object:(nullable id)anObject;
上面这三个方法虽然写法不同,但是功能一样,使用哪一个方法取决于NSNotification类如何创建对象。后两种方法其实就是初始化通知并发送通知,将通知对象的初始化和发送方法结合。
移除通知的方法:
//移除该检测对象(observer)下的所有通知
- (void)removeObserver:(id)observer;
//根据通知名称(aName),移除该检测对象(observer)下的一个通知
- (void)removeObserver:(id)observer name:(nullable NSString *)aName;
如果我们只是想取消某一个通知的注册,而不是全部,那么可以使用第二个方法,将通知名称传过去,就会只取消注册该通知。
注:注册通知和移除通知都是成双成对出现,iOS9.0之前,页面销毁时不移除通知会crash,原因:通知中心对观察者的引用是unsafe_unretained,导致当观察者释放的时候,观察者的指针值并不为nil,出现野指针.
iOS9.0之后,页面销毁时不移除通知不会crash,原因:通知中心对观察者的引用是weak。