IOS KVC,KVO

KVC

KVC是key Value Coding的縮寫,主要方法有setValue:forKey和valueForKey:。

setValue:forKey:主要是賦值。value參數(shù)是值,key參數(shù)是變量名。

eg:[student setValue:@”張3”forKey:@”name”];

給student的name屬性賦值為張3 。

valueForKey: 主要是取值。key是變量名,方法返回變量的值。

setValue:forKeyPath:可以通過“.”的方式,給私有的自定義類型的私有變量賦值。

eg:[student setValue:@”LI4” forKeyPath:@”person.name”];

利用KVC機(jī)制,可以給繼承于NSObject類的私有變量賦值。

注意:

key里面的屬性,是什么類型,value對(duì)應(yīng)的就應(yīng)該是什么類型。

key里面的屬性,一定要是類的屬性,否則會(huì)報(bào)錯(cuò)。

主要用在多個(gè)類,對(duì)象嵌套的時(shí)候。

譬如:

我們有一個(gè)人 這個(gè)人有一個(gè)手機(jī)類 這個(gè)手機(jī)類 有一個(gè)電池類 我們要獲取這個(gè)電池類 比之前復(fù)雜了吧。

沒有KVC

Persion *persion =[ [Persion alloc] init ];

Phone *phone = persion.phone;

Battery *battery = phone.battery;

一:使用KVC

Battery *battery = [persion valueForKeyPath: @"phone.battery" ];

注意- valueForKeyPath 里面的值是區(qū)分大小寫的,你如果寫出Phone.Battery 是不行的.

KVC 最常用的還是在序列化和反序列話對(duì)象。我們經(jīng)常需要把json字符串反序列化成我們想要的對(duì)象 下面是一個(gè)例子 將字典用NSKeyedArchiver 序列化成對(duì)象

- (id)initWithDictionary:(NSDictionary *)dictionary {

self = [self init];

if (self){

[self setValuesForKeysWithDictionary:dictionary];

}

return self;

}

注意 這里有一個(gè)坑 當(dāng)我們setValue 給一個(gè)沒有定義的字典值(forUndefinedKey)時(shí) 會(huì)拋出NSUndefinedKeyException異常的 記的處理此種情況.

還有一個(gè)需要注意的是KVC 并沒有類型檢驗(yàn),畢竟Object-C 還是動(dòng)態(tài)的啦。 還是看下面的代碼吧

[persion setValue:[NSNumber numberWithInteger:1] forKey:@"name"];

// compiles and runs

persion.name = [NSNumber numberWithInteger:1];

// won't compile: Incompatible pointer types assigning to 'NSString *' from 'NSNumber *'

setValue forKey 得到的對(duì)象是泛型的id, 只有在使用的時(shí)候才能確定類型。你可能會(huì)問不至于吧 OC 這樣弱啊,當(dāng)然不是 OC 提供了了一個(gè)方法validateValue來解決這個(gè)問題

@property (nonatomic, strong) NSString name;

- (BOOL)validateName:(id*)ioValue error:(NSError**)error {

// Validation logic goes here

}

Person *p = [Person new];

NSString *name = @"Jason Hu";

NSError *error = nil;

// This call below actually calls our validateName: error: method

if ([p validateValue:&name forKey:@"name" error:&error]) {

[p setValue:name forKey:@"name"];

}

你可能會(huì)問寫這樣多代碼 才只驗(yàn)證了一個(gè)屬性 那如果我這個(gè)類有n+個(gè)屬性 難道我要寫n+個(gè)驗(yàn)證方法嗎?

二:KVC 驗(yàn)證

到這里我們對(duì)KVC已經(jīng)有了一個(gè)初步印象,到這里其實(shí)還只是冰山一角。

下面我們要提高更高的要求,如果讓key 支持 不區(qū)分大小寫

下面我們提到一個(gè)方法initialize

initialize是在類或者其子類的第一個(gè)方法被調(diào)用前調(diào)用。所以如果類沒有被引用進(jìn)項(xiàng)目或者類文件被引用進(jìn)來,但是沒有使用,那么initialize也不會(huì)被調(diào)用 ,到這里 知道我們接下來要干嘛了吧

+ (void)initialize {

[super initialize];

dispatch_once(&onceToken, ^{

modelProperties = [NSMutableDictionary dictionary];

propertyTypesArray = @[/* removed for brevity */];

});

NSMutableDictionary *translateNameDict = [NSMutableDictionary dictionary];

[self hydrateModelProperties:[self class] translateDictionary:translateNameDict];

[modelProperties setObject:translateNameDict forKey:[self calculateClassName]];

}

+ (void)hydrateModelProperties:(Class)class translateDictionary:(NSMutableDictionary *)translateDictionary {

if (!class || class == [NSObject class]){

return;

}

unsigned int outCount, i;

objc_property_t *properties = class_copyPropertyList(class, &outCount);

for (i = 0; i < outCount; i++){

objc_property_t p = properties[i];

const char *name = property_getName(p);

NSString *nsName = [[NSString alloc] initWithCString:name encoding:NSUTF8StringEncoding];

NSString *lowerCaseName = [nsName lowercaseString];

[translateDictionary setObject:nsName forKey:lowerCaseName];

//注意此處哦

NSString *propertyType = [self getPropertyType:p];

[self addValidatorForProperty:nsName type:propertyType];

}

free(properties);

[self hydrateModelProperties:class_getSuperclass(class) translateDictionary:translateDictionary];

}

KVO

Key-Value Observing (簡(jiǎn)寫為KVO):當(dāng)指定的對(duì)象的屬性被修改了,允許對(duì)象接受到通知的機(jī)制。每次指定的被觀察對(duì)象的屬性被修改的時(shí)候,KVO都會(huì)自動(dòng)的去通知相應(yīng)的觀察者,相當(dāng)于設(shè)計(jì)模式中的觀察者模式。

KVO的優(yōu)點(diǎn):

當(dāng)有屬性改變,KVO會(huì)提供自動(dòng)的消息通知。這樣的架構(gòu)有很多好處。首先,開發(fā)人員不需要自己去實(shí)現(xiàn)這樣的方案:每次屬性改變了就發(fā)送消息通知。這是KVO 機(jī)制提供的最大的優(yōu)點(diǎn)。因?yàn)檫@個(gè)方案已經(jīng)被明確定義,獲得框架級(jí)支持,可以方便地采用。開發(fā)人員不需要添加任何代碼,不需要設(shè)計(jì)自己的觀察者模型,直接可 以在工程里使用。其次,KVO的架構(gòu)非常的強(qiáng)大,可以很容易的支持多個(gè)觀察者觀察同一個(gè)屬性,以及相關(guān)的值。

KVO是Key Value Observer的縮寫,主要方法是addObserver:forKeyPath:options:context:和observeValueForPath:ofObject:change:context。

addObserver:forKeyPath:options:context:注冊(cè)監(jiān)聽事件。

observeValueForPath:ofObject:change:context當(dāng)注冊(cè)的值,利用KVC發(fā)生改變的時(shí)候,就會(huì)觸發(fā)這個(gè)方法。

在最后的dealloc方法里面,要記得移除監(jiān)聽事件。

補(bǔ)充:iOS之KVC和KVO

一、KVC(key-value-coding)

1、只針對(duì)類屬性,設(shè)置鍵值對(duì)

2、設(shè)置setValue: forKey:,即forKey只能為類屬性

3、取值valueForKey

二、KVO(key-value-observing)被觀察者的屬性發(fā)生改變時(shí),通知觀察者

1、利用KVC對(duì)類屬性進(jìn)行設(shè)置

2、注冊(cè)observing對(duì)象addObserver:forKeyPath:options:context:

3、觀察者類必須重寫方法?observeValueForKeyPath:ofObject:change:context:

4、應(yīng)用,MVC模型中,數(shù)據(jù)庫(dataModal)發(fā)生變化時(shí),引起view改變,用這種方式實(shí)現(xiàn)非常方便

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • KCV 其實(shí)由于ObjC的語言特性,你根部不必進(jìn)行任何操作就可以進(jìn)行屬性的動(dòng)態(tài)讀寫,這種方式就是Key Value...
    TYM閱讀 1,134評(píng)論 0 4
  • 前言: 本文基本不講KVC/KVO的用法,只結(jié)合網(wǎng)上的資料說說對(duì)這種技術(shù)的理解。 由于KVO內(nèi)容較少,而且是以KV...
    土b蘭博王閱讀 3,158評(píng)論 0 33
  • KVC(Key-value coding)鍵值編碼,單看這個(gè)名字可能不太好理解。其實(shí)翻譯一下就很簡(jiǎn)單了,就是指iO...
    朽木自雕也閱讀 1,693評(píng)論 6 1
  • 1.KVC底層是通過runtime對(duì)method和value操作 比如說如下的一行KVC的代碼: [sit set...
    smart_small閱讀 957評(píng)論 0 0
  • 一、KVC 通過關(guān)鍵字,訪問屬性及成員變量。1.kvc當(dāng)調(diào)用setValue:屬性值 forKey:@”name“...
    doudo閱讀 369評(píng)論 0 0

友情鏈接更多精彩內(nèi)容