1. 程式人生 > >iOS 通知(NSNotification)的簡單使用

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,

copy)NSDictionary *userInfo;

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一樣,要在合理的位置移除。