iOS中通知徘溢、代理、Block捆探、KVO

在一個(gè)復(fù)雜的然爆,有狀態(tài)的系統(tǒng)中,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變徐许,如何通知系統(tǒng),并對狀態(tài)改變做出相應(yīng)的行為是必需考慮的一個(gè)問題卒蘸,在iOS中為這類問題提供了4種解決方法:

1雌隅、NSNotifiactaionNSNotificationCenter:通知中心
2、Delegate:代理
3缸沃、Block:回調(diào)(Callback)
4恰起、KVO(Key-Value Observing):鍵值觀察

一、NSNotification 和 NSNotificationCenter

每個(gè)運(yùn)行中的application都有一個(gè)NSNotificationCenter的成員變量,它的功能就類似公共欄趾牧。對象注冊關(guān)注某個(gè)確定的notification检盼,我們把這些注冊對象叫做 observer。其它的一些對象會給center發(fā)送notifications翘单,center將該notifications轉(zhuǎn)發(fā)給所有注冊對該notification感興趣的對象吨枉,我們把這些發(fā)送notification的對象叫做 poster。
1哄芜、在要發(fā)出通知消息的地方:

[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification_isHaveBanner" object:nil userInfo:@{@"ishavebanner":@"1"}];

2貌亭、在要接收通知消息的地方:

//對象注冊,并關(guān)連消息
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reciveBannernNotice:) name:@"Notification_isHaveBanner" object:nil];
#pragma mark 接收通知處理傳遞消息
-(void) reciveBannernNotice:(NSNotification *)notification
{
    NSString *bannerStr = [notification.userInfo objectForKey:@"ishavebanner"];
    if ([bannerStr isEqualToString:@"0"]) {
        isHaveBanner = NO;
    }else if([bannerStr isEqualToString:@"1"])
    {
        isHaveBanner = YES;
    }else{
        isHaveBanner = NO;
    }
}

一认臊、Delegate(代理)

delegate(代理)是iOS編程的一種設(shè)計(jì)模式圃庭,簡單來說就是一個(gè)委托方的類讓另外一個(gè)代理方的類具體實(shí)現(xiàn)其定義的方法。怎樣寫一個(gè)代理設(shè)計(jì)模式

1失晴、你要明確你的協(xié)議名稱剧腻,一般來講名稱都是:控件類名 + Delegate
2、代理方法中一般都是聲明為@optional(程序默認(rèn)情況下是@required)
3涂屁、代理方法名一般以控件開頭
4书在、代理方法至少有一個(gè)參數(shù)

舉例:來個(gè)保姆和嬰兒之間是怎樣利用代理協(xié)議來實(shí)現(xiàn)一個(gè)簡單的找過過程,嬰兒類要坐的事委托保姆類做拆又。
1蕊温、首先袱箱,我們創(chuàng)建一個(gè)嬰兒類,繼承自NSObject 义矛,接下來在Baby.h文件中創(chuàng)建下面的代碼

#import <Foundation/Foundation.h>

// 定義一份代理協(xié)議
@protocol BabyDelegate <NSObject>
- (void)babyWantEat:(Baby *)baby;
- (void)babyWantSleep:(Baby *)baby;
@end

@interface Baby : NSObject

/** 吃了多少東西 */
@property (nonatomic, assign) int food;
/** 睡意 */
@property (nonatomic, assign) int sleep;

/** 餓了 */
- (void)wantEat;
/** 困了 */
- (void)wantSleep;

/** 代理對象 */
@property (nonatomic, weak) id<BabyDelegate> delegate;
@end

2发笔、接下來是Baby.m文件中創(chuàng)建下面的文件

#import "Baby.h"

@implementation Baby
- (void)wantEat
{
    NSLog(@"嬰兒想吃東西");

    // 通知保姆喂嬰兒
    if ([self.deleate respondsToSelector:@selector(babyWantEat:)]){
        [self.delegate babyWantEat:self];
    }
}

- (void)wantSleep
{
    NSLog(@"嬰兒想睡覺");

    // 通知保姆哄嬰兒睡覺
    if ([self.deleate respondsToSelector:@selector(babyWantSleep:)]){
    [self.delegate babyWantSleep:self];
    }
}

@end

3、下面創(chuàng)建一個(gè)保姆類同樣繼承自NSObject,下面是Nurse.h文件中的代碼

#import "Baby.h"
#import <Foundation/Foundation.h>
@interface Nurse : NSObject <BabyDelegate>
@end

4凉翻、接下來是Nurse.m文件中保姆需要在代理委托方法中做她的工作

#import "Nurse.h"
@implementation Nurse
- (void)babyWantEat:(Baby *)baby
{
    //baby是代理委托方傳過來的值
    baby.food += 20;
    NSLog(@"Nurse喂嬰兒吃東西--現(xiàn)在的食量是%d", baby.food);
}

- (void)babyWantSleep:(Baby *)baby
{
    baby.sleep += 20;

    NSLog(@"Nurse哄嬰兒睡覺--現(xiàn)在的睡意是%d", baby.sleep);
}
@end

三了讨、Block(回調(diào))

直接舉例:一個(gè)Block回調(diào)修改上一界面的背景顏色。

ViewController1 控制器1制轰,ViewController2 控制器2前计。控制器1跳轉(zhuǎn)到控制器2垃杖,然后在控制器2觸發(fā)事件回調(diào)修改控制器1的背景顏色為紅色男杈。

1、ViewController2實(shí)現(xiàn):

#import <UIKit/UIKit.h>
@interface ViewController2 : UIViewController
/**
 *  定義了一個(gè)changeColor的Block调俘。這個(gè)changeColor必須帶一個(gè)參數(shù)伶棒,這個(gè)參數(shù)的類型必須為id類型的
 *  無返回值
 *  @param id
 */
typedef void(^changeColor)(id);
/**
 *  用上面定義的changeColor聲明一個(gè)Block,聲明的這個(gè)Block必須遵守聲明的要求。
 */
@property (nonatomic, copy) changeColor backgroundColor;
@end


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //聲明一個(gè)顏色
    UIColor *color = [UIColor redColor];
    //用剛剛聲明的那個(gè)Block去回調(diào)修改上一界面的背景色
    self.backgroundColor(color);
}

1彩库、ViewController1實(shí)現(xiàn):

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    ViewController2 *vc =[[ViewController2 alloc]init];
    // 回調(diào)修改顏色
    vc.backgroundColor = ^(UIColor *color){
        self.view.backgroundColor = color;
    };
    [self.navigationController pushViewController:vc animated:YES];
}

四肤无、KVO(Key-Value Observing)

KVO是Object-C中定義的一個(gè)通知機(jī)制,其定義了一種對象間監(jiān)控對方狀態(tài)的改變骇钦,并做出反應(yīng)的機(jī)制宛渐。對象可以為自己的屬性注冊觀察者,當(dāng) 這個(gè)屬性的值發(fā)生了改變眯搭,系統(tǒng)會對這些注冊的觀察者做出通知窥翩。其用途十分廣泛,比方說鳞仙,你的下載進(jìn)度條是根據(jù)下載百分比決定的鳍烁,那么,可以通過觀察下載百 分比的改變繁扎,刷新進(jìn)度條的樣式幔荒,來直觀的反應(yīng)下載進(jìn)度等等。

A.注冊觀察者:

//第一個(gè)參數(shù)observer:觀察者 (這里觀察self.myKVO對象的屬性變化)
//第二個(gè)參數(shù)keyPath: 被觀察的屬性名稱(這里觀察self.myKVO中num屬性值的改變)
//第三個(gè)參數(shù)options: 觀察屬性的新值梳玫、舊值等的一些配置(枚舉值爹梁,可以根據(jù)需要設(shè)置,例如這里可以使用兩項(xiàng))
//第四個(gè)參數(shù)context: 上下文提澎,可以為kvo的回調(diào)方法傳值(例如設(shè)定為一個(gè)放置數(shù)據(jù)的字典)
[self.myKVO addObserver:self forKeyPath:@"num" options:
NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
注意:這里的self.myKVO是被觀察的對象姚垃,可以是self本身、也可以是定義的self.tableview等等盼忌。forKeyPath對應(yīng)的一定要是這個(gè)對象的屬性名稱积糯。

B. 屬性(keyPath)的值發(fā)生變化時(shí)掂墓,收到通知,調(diào)用以下方法:

//keyPath:屬性名稱
//object:被觀察的對象
//change:變化前后的值都存儲在change字典中
//context:注冊觀察者時(shí)看成,context傳過來的值
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
   //do something...
}

其他相關(guān)鏈接:開發(fā)該選擇Blocks還是Delegates

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末君编,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子川慌,更是在濱河造成了極大的恐慌吃嘿,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梦重,死亡現(xiàn)場離奇詭異兑燥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)琴拧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門降瞳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚓胸,你說我怎么就攤上這事挣饥。” “怎么了赢织?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵亮靴,是天一觀的道長馍盟。 經(jīng)常有香客問我于置,道長,這世上最難降的妖魔是什么贞岭? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任八毯,我火速辦了婚禮,結(jié)果婚禮上瞄桨,老公的妹妹穿的比我還像新娘话速。我一直安慰自己,他們只是感情好芯侥,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布泊交。 她就那樣靜靜地躺著,像睡著了一般柱查。 火紅的嫁衣襯著肌膚如雪廓俭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天唉工,我揣著相機(jī)與錄音研乒,去河邊找鬼。 笑死淋硝,一個(gè)胖子當(dāng)著我的面吹牛雹熬,可吹牛的內(nèi)容都是我干的宽菜。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼竿报,長吁一口氣:“原來是場噩夢啊……” “哼铅乡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起仰楚,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤隆判,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后僧界,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侨嘀,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年捂襟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咬腕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,912評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡葬荷,死狀恐怖涨共,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宠漩,我是刑警寧澤举反,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站扒吁,受9級特大地震影響火鼻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜雕崩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一魁索、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盼铁,春花似錦粗蔚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肤寝,卻和暖如春当辐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背醒陆。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工瀑构, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓寺晌,卻偏偏與公主長得像世吨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子呻征,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容