Objective-C KVC和KVO的使用

KVC的使用

通常情況下,我們都是通過屬性或者定義存取方法來對(duì)實(shí)例變量進(jìn)行存取,但是除此之外芹橡,我們也可以通過Key-Value-Coding(KVC)鍵值編碼來存取的實(shí)例變量的值前弯。
使用KVC過程:
首先,我們定義一個(gè)Person類修肠,代碼如下:

/*
*Person.h
*/
#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    NSString *_name;
}
@end

/*
*Person.m
*/
#import "Person.h"

@implementation Person

@end

然后創(chuàng)建Person類的實(shí)例贺辰,并使用KVC對(duì)_name實(shí)例變量進(jìn)行賦值和取值操作:

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
     //將person的實(shí)例變量_name賦值為SmithJackyson
        [person setValue:@"SmithJackyson" forKey:@"_name"];
     //取出person的實(shí)例變量_name的值
        NSString *name = [person valueForKey:@"_name"];
        NSLog(@"name = %@",name);
    }
    return 0;
}

下面為打印結(jié)果:
2016-01-14 20:42:14.098 test[1559:113739] name = SmithJackyson
Program ended with exit code: 0

如果A類的屬性是一個(gè)B類,那么為B類的屬性存取值就需要鍵路徑訪問屬性
假設(shè)Student類有一個(gè)Course類的屬性_course,其中Course類有一個(gè)屬性表示課程名稱NSString *_courseName;
下面通過鍵路徑訪問屬性:

#import <Foundation/Foundation.h>
#import "Student.h"
#import "Course.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //注意:使用KVC是為實(shí)例存取實(shí)例變量饲化,所以要初始化莽鸭,并且為student的_course實(shí)例變量賦值為course,否則無法正確賦值
        Student *student = [[Student alloc] init];
        Course *course = [[Course alloc] init];
        [student setValue:course forKey:@"_course"];

        //為student實(shí)例變量_course的屬性_courseName賦值
        [student setValue:@"English" forKeyPath:@"_course._courseName"];

        //取得student實(shí)例變量_course的屬性_courseName的值
        NSString *courseName = [student valueForKeyPath:@"_course._courseName"];
        NSLog(@"courseName = %@",courseName);
    }
    return 0;
}

下面是打印結(jié)果:
2016-01-14 21:15:59.094 test[1867:123245] courseName = English
Program ended with exit code: 0
如果屬性是基本數(shù)據(jù)類型吃靠,可以使用字符串值直接賦值給屬性硫眨,取值時(shí)用字符串變量接受

KVO的使用

KVO,即:key-value observing巢块,提供一種機(jī)制礁阁,假設(shè)A對(duì)象觀察B對(duì)象的指定屬性C,當(dāng)B對(duì)象的屬性C的值發(fā)生變化族奢,KVO會(huì)通知相應(yīng)的觀察者A乓序,A對(duì)象可以進(jìn)行某些操作,比如更新視圖
使用過程:

  1. 注冊(cè)霜威,指定觀察哪些對(duì)象的哪些屬性
  2. 實(shí)現(xiàn)回調(diào)方法
  3. 移除觀察

首先定義一個(gè)Person類眨猎,代碼如下:

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic,copy)NSString *name;

- (instancetype)initWithName:(NSString *)name;

@end


#import "Person.h"

@implementation Person

- (instancetype)initWithName:(NSString *)name
{
    self = [super init];
    if (self) {
        _name = name;
    }
    return self;
}

@end

然后在ViewController中使用KVO,代碼如下:

#import "ViewController.h"
#import "Person.h"

@interface ViewController ()
{
    Person *person;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    person = [[Person alloc] initWithName:@"John"];
    //為person對(duì)象的屬性name添加觀察者為ViewController
    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    //可以通過下面兩種方式改變name的值弥姻,都會(huì)觸發(fā)回調(diào)方法
    person.name = @"SmithJackyson";
    [person setValue:@"SmithJackyson" forKey:@"name"];
}

//實(shí)現(xiàn)KVO回調(diào)方法南片,只要person的屬性name發(fā)生變化,就會(huì)回調(diào)這個(gè)方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
   //change字典里存的內(nèi)容是根據(jù)你注冊(cè)時(shí)的選項(xiàng)option決定的庭敦,如果為NSKeyValueObservingOptionNew疼进,則字典里存的是改變后的值,key為new秧廉,同樣NSKeyValueObservingOptionOld伞广,則字典里存的是改變前的值,key為old疼电,如果兩者都有嚼锄,則字典存儲(chǔ)著兩個(gè)值
    if ([keyPath isEqualToString:@"name"] && object == person) {
        NSLog(@"now name = %@",person.name);
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

運(yùn)行結(jié)果如下:
2016-01-15 16:17:29.102 test[1752:94898] now name = SmithJackyson
2016-01-15 16:17:29.102 test[1752:94898] now name = SmithJackyson
最后還需要移除觀察者

- (void)dealloc
{
    [person removeObserver:self forKeyPath:@"name"];
}

當(dāng)需要手動(dòng)通知時(shí),可以重寫Person類的下面的方法告訴cocoa哪些鍵值要使用自動(dòng)通知:

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
   if([key isEqualToString:@"name"]) {
        return NO;
}    
  return [super automaticallyNotifiesObserversForKey:key];
}

返回YES表示自動(dòng)通知蔽豺,當(dāng)返回NO時(shí)区丑,表示手動(dòng)通知,在值發(fā)生變化時(shí)需要調(diào)用willChangeValueForKey:和didChangeValueForKey:方法通知調(diào)用者修陡。


轉(zhuǎn)載請(qǐng)注明:作者SmithJackyson

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沧侥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子魄鸦,更是在濱河造成了極大的恐慌宴杀,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拾因,死亡現(xiàn)場(chǎng)離奇詭異旺罢,居然都是意外死亡斯棒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門主经,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荣暮,“玉大人,你說我怎么就攤上這事罩驻∷胨郑” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵惠遏,是天一觀的道長砾跃。 經(jīng)常有香客問我,道長节吮,這世上最難降的妖魔是什么抽高? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮透绩,結(jié)果婚禮上翘骂,老公的妹妹穿的比我還像新娘。我一直安慰自己帚豪,他們只是感情好碳竟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著狸臣,像睡著了一般莹桅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上烛亦,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天诈泼,我揣著相機(jī)與錄音,去河邊找鬼煤禽。 笑死铐达,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的呜师。 我是一名探鬼主播娶桦,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贾节,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼汁汗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起栗涂,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤知牌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后斤程,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體角寸,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菩混,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扁藕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沮峡。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖亿柑,靈堂內(nèi)的尸體忽然破棺而出邢疙,到底是詐尸還是另有隱情,我是刑警寧澤望薄,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布疟游,位于F島的核電站,受9級(jí)特大地震影響痕支,放射性物質(zhì)發(fā)生泄漏颁虐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一卧须、第九天 我趴在偏房一處隱蔽的房頂上張望另绩。 院中可真熱鬧,春花似錦花嘶、人聲如沸板熊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽干签。三九已至,卻和暖如春拆撼,著一層夾襖步出監(jiān)牢的瞬間容劳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工闸度, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留竭贩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓莺禁,卻偏偏與公主長得像留量,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哟冬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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