通知中心

  • ** 通知機制(消息機制)是一個應用程序級別的操作UIApplication
  • 通知中心實際上是iOS程序內部之間的一種消息廣播機制,主要為了解決應用程序內部不同對象之間解耦而設計。它是基于觀察者模式設計的,不能跨應用程序進程通信,當通知中心接收到消息之后會根據內部的消息轉發表,將消息發送給訂閱者

通知機制 與 NSNotification 區別

  • NSNotification是抽象的,不可見的
  • 推送通知是可見的(能用肉眼看到)
  • 對于很多初學者往往會把iOS中的本地通知、推送通知和iOS通知中心的概念弄混。其實二者之間并沒有任何關系,事實上它們都不屬于一個框架,前者屬于UIKit框架,后者屬于Foundation框架。
    下面是一個簡單的通知中心流程示意圖:
屏幕快照 2016-03-27 下午2.06.52.png

了解通知中心需要熟悉NSNotificationCenter和NSNotification兩個類:

  • NSNotificationCenter:是通知系統的中心,用于注冊和發送通知,下表列出常用的方法
屏幕快照 2016-03-27 下午2.13.03.png
  • NSNotification:代表通知內容的載體,主要有三個屬性:name代表通知名稱,object代表通知的發送者,userInfo代表通知的附加信息。

  • 很多東西都是通過通知中心來進行應用中各個組件通信。例如說道應用程序生命周期問題,當應用程序啟動后、進入后臺、進入前臺、獲得焦點、失去焦點,窗口大小改變、隱藏等都會發送通知。這個通知可以通過前面NSNotificationCenter進行訂閱即可接收對應的消息,下面的示例演示如何添加監聽獲得UIApplication的進入后臺和獲得焦點的通知:

//
//  LTYViewController.m
//  NotificationCenter
//

#import "LTYViewController.h"

@interface LTYViewController ()

@end

@implementation LTYViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self addObserverToNotificationCenter];
    
}

#pragma mark 添加監聽
-(void)addObserverToNotificationCenter{
    /*添加應用程序進入后臺監聽
     * observer:監聽者
     * selector:監聽方法(監聽者監聽到通知后執行的方法)
     * name:監聽的通知名稱(下面的UIApplicationDidEnterBackgroundNotification是一個常量)
     * object:通知的發送者(如果指定nil則監聽任何對象發送的通知)
     */
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication]];
    
    /* 添加應用程序獲得焦點的通知監聽
     * name:監聽的通知名稱
     * object:通知的發送者(如果指定nil則監聽任何對象發送的通知)
     * queue:操作隊列,如果制定非主隊線程隊列則可以異步執行block
     * block:監聽到通知后執行的操作
     */
    NSOperationQueue *operationQueue=[[NSOperationQueue alloc]init];
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:[UIApplication sharedApplication] queue:operationQueue usingBlock:^(NSNotification *note) {
        NSLog(@"Application become active.");
    }];
}

#pragma mark 應用程序啟動監聽方法
- (void)applicationEnterBackground{
    NSLog(@"Application enter background.");
}
@end
  • 當然很多時候使用通知中心是為了添加自定義通知,并獲得自定義通知消息。比如多視圖之間參數傳遞,其實利用自定義通知也可以進行參數傳遞。通常一個應用登錄后會顯示用戶信息,而登錄信息可以通過登錄界面獲取。下面就以這樣一種場景為例,在主界面中添加監聽,在登錄界面發送通知,一旦登錄成功將向通知中心發送成功登錄的通知,此時主界面中由于已經添加通知監聽所以會收到通知并更新UI界面。

主界面LTYViewController.m

//
//  LTYViewController.m
//  NotificationCenter
//

#import "LTYViewController.H"
#import "LTYoginViewController.h"
#define UPDATE_LGOGIN_INFO_NOTIFICATION @"updateLoginInfo"

@interface LTYViewController () {
    UILabel *_lbLoginInfo;
    UIButton *_btnLogin;
}

@end

@implementation LTYViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupUI];
}

- (void)setupUI{
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100,320 ,30)];
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor=[UIColor colorWithRed:23/255.0 green:180/255.0 blue:237/255.0 alpha:1];
    _lbLoginInfo = label;
    [self.view addSubview:label];
    
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    button.frame=CGRectMake(60, 200, 200, 25);
    [button setTitle:@"登錄" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(loginOut) forControlEvents:UIControlEventTouchUpInside];
    _btnLogin = button;
    
    [self.view addSubview:button];
}

- (void)loginOut{
    //添加監聽
    [self addObserverToNotification];
    
    LTYLoginViewController *loginController=[[LTYLoginViewController alloc] init];
    
    [self presentViewController:loginController animated:YES completion:nil];
}

/**
 *  添加監聽
 */
- (void)addObserverToNotification{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateLoginInfo:) name:UPDATE_LGOGIN_INFO_NOTIFICATION object:nil];
}

/**
 *  更新登錄信息,注意在這里可以獲得通知對象并且讀取附加信息
 */
- (void)updateLoginInfo:(NSNotification *)notification{
    NSDictionary *userInfo=notification.userInfo;
    _lbLoginInfo.text=userInfo[@"loginInfo"];
    _btnLogin.titleLabel.text=@"注銷";
}

- (void)dealloc{
    //移除監聽
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

登錄界面LTYLoginViewController.m

//
//  LTYLoginViewController.m
//  NotificationCenter
//

#import "LTYLoginViewController.H"
#define UPDATE_LGOGIN_INFO_NOTIFICATION @"updateLoginInfo"

@interface LTYLoginViewController (){
    UITextField *_txtUserName;
    UITextField *_txtPassword;
}

@end

@implementation LTYLoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setupUI];
}

/**
 *  UI布局
 */
- (void)setupUI{
    //用戶名
    UILabel *lbUserName=[[UILabel alloc]initWithFrame:CGRectMake(50, 150, 100, 30)];
    lbUserName.text=@"用戶名:";
    [self.view addSubview:lbUserName];
    
    _txtUserName=[[UITextField alloc]initWithFrame:CGRectMake(120, 150, 150, 30)];
    _txtUserName.borderStyle=UITextBorderStyleRoundedRect;
    [self.view addSubview:_txtUserName];
    
    //密碼
    UILabel *lbPassword=[[UILabel alloc]initWithFrame:CGRectMake(50, 200, 100, 30)];
    lbPassword.text=@"密碼:";
    [self.view addSubview:lbPassword];
    
    _txtPassword=[[UITextField alloc]initWithFrame:CGRectMake(120, 200, 150, 30)];
    _txtPassword.secureTextEntry=YES;
    _txtPassword.borderStyle=UITextBorderStyleRoundedRect;
    [self.view addSubview:_txtPassword];
    
    //登錄按鈕
    UIButton *btnLogin=[UIButton buttonWithType:UIButtonTypeSystem];
    btnLogin.frame=CGRectMake(70, 270, 80, 30);
    [btnLogin setTitle:@"登錄" forState:UIControlStateNormal];
    [self.view addSubview:btnLogin];
    [btnLogin addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
    
    //取消登錄按鈕
    UIButton *btnCancel=[UIButton buttonWithType:UIButtonTypeSystem];
    btnCancel.frame=CGRectMake(170, 270, 80, 30);
    [btnCancel setTitle:@"取消" forState:UIControlStateNormal];
    [self.view addSubview:btnCancel];
    [btnCancel addTarget:self action:@selector(cancel) forControlEvents:UIControlEventTouchUpInside];
}

#pragma mark 登錄操作
-(void)login{
    if ([_txtUserName.text isEqualToString:@"ayuan"] && [_txtPassword.text isEqualToString:@"123"] ) {
        //發送通知
        [self postNotification];
        [self dismissViewControllerAnimated:YES completion:nil];
    }else{
        //登錄失敗彈出提示信息
        UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"系統信息" message:@"用戶名或密碼錯誤,請重新輸入!" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil];
        [alertView show];
    }
    
}

#pragma mark 點擊取消
-(void)cancel{
    [self dismissViewControllerAnimated:YES completion:nil];
}

/**
 *  添加通知,注意這里設置了附加信息
 */
-(void)postNotification{
    NSDictionary *userInfo=@{@"loginInfo":[NSString stringWithFormat:@"Hello,%@!",_txtUserName.text]};
    NSLog(@"%@",userInfo);
    NSNotification *notification=[NSNotification notificationWithName:UPDATE_LGOGIN_INFO_NOTIFICATION object:self userInfo:userInfo];
   [[NSNotificationCenter defaultCenter] postNotification:notification];
//也可直接采用下面的方法
//    [[NSNotificationCenter defaultCenter] postNotificationName:UPDATE_LGOGIN_INFO_NOTIFICATION object:self userInfo:userInfo];

}
@end
  • 通知中心是一種低耦合設計,和代理模式有異曲同工之妙。相對于后者而言,通知中心可以將一個通知發送給多個監聽者,而每個對象的代理卻只能有一個。當然代理也有其優點,例如使用代理代碼分布結構更加清晰,它不像通知一樣隨處都可以添加訂閱等,實際使用過程中需要根據實際情況而定。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容