版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.07.17 |
前言
與代理相比,通知具有低耦合的特點跋核,兩個毫無關(guān)聯(lián)的控制器之間可以進(jìn)行相互通信并相應(yīng)操作薯酝,用了通知很久,但是從沒有系統(tǒng)的總結(jié)一下通知相關(guān)的知識和遇到的坑母截,下面就講一下通知的相關(guān)知識到忽,先從簡單的知識點和API開始。
通知基礎(chǔ)
通知是ios中的一種消息機(jī)制清寇,觀察者只要向消息中心注冊喘漏, 即可接受其他對象發(fā)送來的消息,消息發(fā)送者和消息接受者兩者可以互相一無所知华烟,完全解耦翩迈。這種消息通知機(jī)制可以應(yīng)用于任意時間和任何對象,觀察者可以有多個盔夜,所以消息具有廣播的性質(zhì)负饲,只是需要注意的是,觀察者向消息中心注冊以后喂链,在不需要接受消息時需要向消息中心注銷返十,這種消息廣播機(jī)制是典型的“Observer”(觀察者)模式。
消息機(jī)制常常用于在向服務(wù)器端請求數(shù)據(jù)或者提交數(shù)據(jù)的場景椭微,在和服務(wù)器端成功交互后洞坑,需要處理服務(wù)器端返回的數(shù)據(jù),或發(fā)送響應(yīng)消息等蝇率,就需要用到消息機(jī)制迟杂。其原理主要如下所示:
API
下面我們看一下ios中通知相關(guān)的API。
NSNotification
/**************** Notifications ****************/
@interface NSNotification : NSObject <NSCopying, NSCoding>
@property (readonly, copy) NSNotificationName name;
@property (nullable, readonly, retain) id object;
@property (nullable, readonly, copy) NSDictionary *userInfo;
- (instancetype)initWithName:(NSNotificationName)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
@interface NSNotification (NSNotificationCreation)
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullable id)anObject;
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;
- (instancetype)init /*NS_UNAVAILABLE*/; /* do not invoke; not a valid initializer for this class */
@end
這里面有幾點:
- name:通知的名字本慕,其實就是為通知起的別名排拷,作用就是用以區(qū)分不同通知,如果為nil標(biāo)識可以接收任何名字的通知间狂。
- object :發(fā)送通知的對象攻泼,用以區(qū)分是誰發(fā)出的通知火架,如果為nil鉴象,表示可以接受任何對象發(fā)送的通知忙菠。
- userInfo:它是一個字典用來存儲發(fā)送的通知信息,當(dāng)我們post一個通知的時候纺弊,就可以存放在字典里面牛欢,add監(jiān)聽端,就可以將這個userInfo取出來淆游,得到通知的內(nèi)容傍睹。
- 接下里的幾個對象方法和類方法中存儲的就是通知的初始化或者實例化方法。
** NSNotificationCenter**
/**************** Notification Center ****************/
@interface NSNotificationCenter : NSObject {
@package
void *_impl;
void *_callback;
void *_pad[11];
}
#if FOUNDATION_SWIFT_SDK_EPOCH_AT_LEAST(8)
@property (class, readonly, strong) NSNotificationCenter *defaultCenter;
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject;
#endif
- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(nullable NSNotificationName)aName object:(nullable id)anObject;
- (id <NSObject>)addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block NS_AVAILABLE(10_6, 4_0);
// The return value is retained by the system, and should be held onto by the caller in
// order to remove the observer with removeObserver: later, to stop observation.
@end
這里涉及到的就是通知的轉(zhuǎn)發(fā)犹菱、監(jiān)聽以及移除等拾稳,這個后續(xù)會詳細(xì)說明。
通知的發(fā)送
有關(guān)通知發(fā)送的方法主要有三個腊脱,如下:
- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;
我們先說一下相關(guān)參數(shù)访得,這里的參數(shù)和注冊觀察者時候的參數(shù)也都是一樣的,說一遍就不多說了陕凹。
- notification:通知對象悍抑,通知中心發(fā)出的對象就是它。
- aName:通知的名字杜耙,用以區(qū)分不同通知搜骡,在注冊觀察者的時候,傳nil表示可以監(jiān)聽任何名稱的通知佑女。
- anObject:發(fā)送通知的對象记靡,如果傳nil表示不關(guān)心是誰發(fā)送的通知,觀察者那邊傳入nil表示可以接受任何發(fā)送者的通知团驱。
- aUserInfo:通知消息簸呈,是一個字典,發(fā)送的內(nèi)容可以寫在里面店茶。
第一種發(fā)送通知
//第一種發(fā)送通知
NSNotification *notification = [NSNotification notificationWithName:@"notificationTestOne" object:self];
[[NSNotificationCenter defaultCenter] postNotification:notification];
這里的object也可以為nil蜕便,表示不區(qū)分是誰發(fā)送的。
第二種發(fā)送通知
//第二種發(fā)送通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"notificationTestTwo" object:self];
同上贩幻,就不多說了轿腺。
第三種發(fā)送通知
//第三種發(fā)送通知
NSDictionary *notiDict = @{@"key":@"content"};
[[NSNotificationCenter defaultCenter] postNotificationName:@"notificationTestThree" object:self userInfo:notiDict];
這里,當(dāng)沒有什么傳遞的時候丛楚,userInfo可以為空族壳,為空的時候就和前兩種發(fā)送通知是一樣的了。
通知的監(jiān)聽
通知是一種觀察者模式趣些,有人發(fā)送就要有人observer仿荆,并調(diào)用相關(guān)方法,處理相關(guān)邏輯。下面我們就接受一下上面三種發(fā)送的通知拢操。
第一種監(jiān)聽通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(processTestOne:) name:@"notificationTestOne" object:nil];
- (void)processTestOne:(NSNotification *)noti
{
NSLog(@"notificationTestOne");
}
我們看輸出
2017-07-17 16:18:57.708 JJNotification[17071:1508348] notificationTestOne
可見锦亦,可以收到通知。
第二種監(jiān)聽通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(processTestTwo:) name:@"notificationTestTwo" object:nil];
- (void)processTestTwo:(NSNotification *)noti
{
NSLog(@"notificationTestTwo");
}
下面看輸出
2017-07-17 16:24:20.773 JJNotification[17096:1537087] notificationTestTwo
可見令境,可以收到通知杠园。
第三種監(jiān)聽通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(processTestThree:) name:@"notificationTestThree" object:nil];
- (void)processTestThree:(NSNotification *)noti
{
NSDictionary *notiDict = noti.userInfo;
NSString *content = [notiDict objectForKey:@"key"];
NSLog(@"notificationTestThree = %@",content);
}
下面看輸出
2017-07-17 16:24:20.773 JJNotification[17096:1537087] notificationTestThree = content
可見,還是可以監(jiān)聽到通知舔庶。
通知的移除
不用的監(jiān)聽通知要移除抛蚁,移除通知一般都是在delloc中完成,在delloc中可以移除全部監(jiān)聽的通知惕橙,還可以移除指定名字的通知瞧甩。
移除全部通知
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
如果這么寫,那么上面三個notificationTestOne
弥鹦、notificationTestTwo
亲配、notificationTestThree
通知都會被移除,可謂一勞永逸惶凝。
移除指定名字的通知
但是有的時候的需求是只要移除指定的某個通知吼虎,而保留某一個或者幾個通知,具體如下所示:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"notificationTestOne" object:nil];
}
這樣子就把名字為notificationTestOne
的通知移除了苍鲜,其他的通知還會起作用思灰,保留著監(jiān)聽的功能。
后記
這里寫的就是ios API以及通知的監(jiān)聽混滔、發(fā)送以及移除等基本知識洒疚,目的就是給新手能看明白,后面的幾篇我會加入稍微難一點的東西還有就是一些通知過程中碰到的坑坯屿。