iOS 通知(NSNotification)的簡單使用
通知:NSNotification,是iOS開發中一種重要的設計模式,它的實質是程式內部提供的一種廣播機制。把接受到的訊息根據內部訊息轉發表,將訊息轉發給需要的物件。
通知這種設計模式,在開發中常用來不同類之間的通訊,也就是常說的頁面之間的傳值。當然它不僅僅只有這一種應用場景,還有一種常用場景是用來控制一些屬性或者控制元件,使得這些屬性或控制元件在不同情況下發生響應的變化。在我以前的一個專案中就有這樣的場景出現:
專案需求:每次開啟app和每次需要下載時監控網路狀態變化,當時WiFi狀態是開啟自動下載開關,非WiFi狀態時關閉自動下載開關。
對於這樣的需求,就可以使用通知去實現,而且很簡單,只需要在需要傳送通知的地方,註冊、傳送通知,在開關存在的地方接受通知訊息,根據通知去控制開關是開啟還是關閉。
那麼,下面介紹如何使用通知。
首先先介紹一下幾個類:
1、NSNotification
這個類是通知類,由這個類建立的物件是一個通知物件,也可以理解為是一個訊息物件。類中有三個成員變數:
name:是訊息物件的唯一標識,接受通知訊息時用來辨別
@property (readonly,copy)NSNotificationName name;
object:一個物件,可以理解為針對某個物件的訊息
@property (nullable,readonly,retain)id object;
userInfo:一個字典,用來傳值
@property (nullable,readonly,
NSNotification初始化:
物件方法初始化一個通知物件,並給通知物件的屬性賦值
- (instancetype)initWithName:(NSNotificationName)name object:(nullableid)object userInfo:(nullableNSDictionary *)userInfoNS_AVAILABLE(10_6, 4_0) NS_DESIGNATED_INITIALIZER;
類方法建立一個通知物件,這個方法沒有userInfo這個屬性的初始賦值,所以用來發送無傳值的通知
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullableid)anObject;
類方法初始化一個通知物件,並給通知物件的屬性賦值
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullableid)anObject userInfo:(nullableNSDictionary *)aUserInfo;
注意:NSNotification不可以使用init進行初始化。
2、NSNotificationCenter
這個類是通知中心類,內部實現是單利模式,每個程式都有一個預設的通知中心,用來排程通知的傳送和接受。
通知中心類相關方法:
a、接收通知的方法:
新增觀察者,可以指定一個方法、名稱和物件,接受到通知時執行這個指定的方法。這裡的name就是通知類的name,只有對應才能接受到通知。
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullableNSNotificationName)aName object:(nullableid)anObject;
b、傳送通知的方法:
傳送通知,引數是一個通知物件
- (void)postNotification:(NSNotification *)notification;
傳送通知,引數是通知的名稱,指定的物件
- (void)postNotificationName:(NSNotificationName)aName object:(nullableid)anObject;
傳送通知,引數是通知的名稱,指定的物件和傳遞的引數
- (void)postNotificationName:(NSNotificationName)aName object:(nullableid)anObject userInfo:(nullableNSDictionary *)aUserInfo;
上面這三個方法雖然寫法不同,但是功能一樣,使用哪一個方法取決於NSNotification類如何建立物件。後兩種方法其實就是初始化通知併發送通知,將通知物件的初始化和傳送方法結合。
c、移除通知的方法:
移除該檢測物件(observer)下的所有通知
- (void)removeObserver:(id)observer;
根據通知名稱(aName),移除該檢測物件(observer)下的一個通知
- (void)removeObserver:(id)observer name:(nullableNSNotificationName)aName object:(nullableid)anObject;
一個通知的初始化,傳送,接收。就是對上面這些方法的使用。
下面,示例說明:
#import "ViewController.h"
@interface ViewController ()
{
UILabel *label;
UIButton *button;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
//建立檢視方法
[selfsetUI];
//建立通知中心物件
NSNotificationCenter *center = [NSNotificationCenterdefaultCenter];
//註冊、接收通知
[center addObserver:selfselector:@selector(chanegeLabelText:)name:@"notification"object:nil];
}
- (void)setUI{
label = [[UILabelalloc]initWithFrame:CGRectMake(100, 200, 200, 30)];
label.backgroundColor = [UIColoryellowColor];
label.text =@"沒有接收到通知";
[self.viewaddSubview:label];
button = [UIButtonbuttonWithType:UIButtonTypeCustom];
button.frame =CGRectMake(100, 300, 200, 30);
[buttonsetTitle:@"傳送通知"forState:UIControlStateNormal];
[buttonsetBackgroundColor:[UIColorblueColor]];
[buttonaddTarget:selfaction:@selector(post)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:button];
}
//按鈕點選方法
- (void)post{
//初始化一個通知物件,名稱是 notification 沒有指定物件 穿的值是一個字典@{@"key":@"an object"}
NSNotification *notification = [NSNotificationnotificationWithName:@"notification"object:niluserInfo:@{@"key":@"接收到了通知"}];
[[NSNotificationCenterdefaultCenter]postNotification:notification];
}
//接收通知後呼叫的方法
- (void)chanegeLabelText:(NSNotification *)noti{
//這個方法的引數就是傳送通知postNotification:方法的引數傳送過來額通知。當要使用傳遞的userInfo的時候,就要使用noti解析出userInfo中需要的欄位
label.text = [noti.userInfoobjectForKey:@"key"];
}
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
//在頁面消失的回撥方法中移除通知。
[[NSNotificationCenterdefaultCenter]removeObserver:selfname:@"notification"object:nil];
}
@end
點選按鈕前: 點選按鈕後:
在上面的顯示中可以看到程式碼沒有問題。
上面的示例只是為了介紹通知的使用而寫的,在實際開發中並不會有這樣實現功能的做法。通知的使用是為了實現不同控制器,或者不同類之間的通訊從而實現一些解耦。在同一個類中一般是沒有資訊傳遞的。
而且,要牢記一點,通知既然是程式內部的一種廣播機制,那麼它的存在就是通訊。
關於通知的使用就是,註冊、接收通知(addObserver)--->傳送通知(postNotification)--->移除通知(removeObserver)。
這裡關於移除通知和前面的KVO那篇文章中移除KVO一樣,要在合理的位置移除。