KVO KVO 溫習(xí)

KVC 與 KVO 是 Objective-C 的關(guān)鍵概念.

KVC:

KVC,即是指 NSKeyValueCoding, 一個(gè)非正式的 Protocol, 提供一種機(jī)制來間接訪問對(duì)象的屬性. KVO就是基于KVC實(shí)現(xiàn)的關(guān)鍵技術(shù)之一.

一個(gè)對(duì)象擁有某些屬性.比如說,一個(gè)Person對(duì)象有一個(gè)name 和一個(gè)address屬性.以KVC說法,Person 對(duì)象分別有一個(gè)value對(duì)應(yīng)他的 name和address的key. key只是一個(gè)字符串,它對(duì)應(yīng)的值可以是任意類型的對(duì)象. 從最基礎(chǔ)的層次上看,KVC有一兩個(gè)方法: 一個(gè)是設(shè)置key的值,另一個(gè)是獲取key的值.如下面的例子:

void changeName(Person *p, NSString *newName){

//using the KVC accessor (getter) method

NSString *originalName = [p valueForKey:@"name"];

//using the KVC accessor (setter) method

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

NSLog(Changed %@'s name to: %@", originalName, newName);

}

現(xiàn)在,如果Person 有另一個(gè)key 配偶(spouse),spouse的key值是另一個(gè)Person對(duì)象,用KVC可以這樣寫:

void logMarriage(Person *p){

// just using the accessor again, same as example above

NSString *personsName =[p valueForKey:@"name"];

// this line is different, because it is using

// a "key path" instead of a normal "key"

NSString *spousesName = [p valueForKeyPath:@"spouse.name"];

NSLog(@"%@ is happily married to %@", personsName, spousesName);

}

key與 key pat 要區(qū)分開來,key可以從一個(gè)對(duì)象中獲取值,而key path 可以將多個(gè)key用點(diǎn)號(hào)"." 分隔連接起來,比如:

[p valueForKeyPath:@"spouse.name"];

相當(dāng)于這樣.....

[[p valueForKey:@"spouse"] valueForKey: @"name"];

# iOS 中KVC的總結(jié) ##

一、 KVC介紹

kvc就是鍵值編碼(key-value),說白了就是通過指定的key獲得想要的值value。而不是通過調(diào)用Setter、Getter方法訪問。*

二、 KVC的強(qiáng)大之處

1 .訪問私有變量

一個(gè)類中的私有變量,不能直接通過Setter、Getter方法訪問。但是卻可以通過KVC來訪問。舉例:

一個(gè)類如下:

@interfaceDog : NSObject{@private

double height;

}

這里的私有變量 height ,假如直接使用Setter、Getter方法訪問,就會(huì)出現(xiàn)下面的錯(cuò)誤。

這時(shí)候可以使用KVC來訪問這個(gè)私有變量:

Dog *dog = [[Dog alloc]init];[dogsetValue:@12forKey:@"height"];//給私有變量賦值NSLog(@"dog's height is = %@",[dogvalueForKey:@"height"]);//讀取私有變量的值

實(shí)際使用舉例

利用kvc的這個(gè)特性,我們可以訪問系統(tǒng)里的一些私有變量。

例如:在UIPageControl里面有兩個(gè)私有變量:

UIImage*? ? ? ? _currentPageImage;UIImage*? ? ? ? _pageImage;

我們可以通過kvc來進(jìn)行讀取和賦值:

UIPageControl *pageControl = [[UIPageControl alloc]init];//設(shè)置值[pageControlsetValue:[UIImageimageNamed:@"XX"]forKeyPath:@"_currentPageImage"];[pageControlsetValue:[UIImageimageNamed:@"XX"]forKeyPath:@"_pageImage"];//讀取值UIImage *currentImage = [pageControlvalueForKey:@"_currentPageImage"];UIImage *pageImage = [pageControlvalueForKey:@"_pageImage"];

這樣我們就可以設(shè)置當(dāng)前顯示和未顯示到腳標(biāo)的樣式了。

2. 使用KVC直接訪問 NSArray 或者 NSSet 的屬性值

NSArray/NSSet等都支持KVC,這里舉一個(gè)例子:

NSArray *books= @[book1, book2, book3];NSArray *names = [booksvalueForKeyPath:@"name"];NSLog(@"%@", [booksvalueForKeyPath:@"@avg.price"]);//使用kvc直接打印出來書的平均價(jià)格

其中,book是一個(gè)書類,有一個(gè)屬性是name,一個(gè)屬性是price。

3. 使用KVC將字典(json)轉(zhuǎn)化成模型

// 定義一個(gè)字典NSDictionary *dict = @{@"name"? :@"jack",@"money" :@"20.7",? ? ? ? ? ? ? ? ? ? ? ? };// 創(chuàng)建模型? ? Person *p = [[Person alloc] init];// 字典轉(zhuǎn)模型? ? [p setValuesForKeysWithDictionary:dict];NSLog(@"person's name is the %@",p.name);

}

注意:

(1). key的值必須正確,如果拼寫錯(cuò)誤,會(huì)出現(xiàn)異常

(2). 當(dāng)key的值是沒有定義的,valueForUndefinedKey:這個(gè)方法會(huì)被調(diào)用,如果你自己寫了這個(gè)方法,key的值出錯(cuò)就會(huì)調(diào)用到這里來

(3). 因?yàn)轭恔ey反復(fù)嵌套,所以有個(gè)keyPath的概念,keyPath就是用.號(hào)來把一個(gè)一個(gè)key鏈接起來,這樣就可以根據(jù)這個(gè)路徑訪問下去

(4). NSArray/NSSet等都支持KVC



KVO:

Key-Value Observing (KVO)

Key-Value Observing(KVO)建立在KVC之上 ,它能夠觀察一個(gè)對(duì)象的KVC key path 值的變化.舉個(gè)例子,用代碼觀察一個(gè)person對(duì)象的address變化,以下是實(shí)現(xiàn)的三個(gè)方法:

.watchPersonForChangeOfAddress:實(shí)現(xiàn)觀察

.observeValueForKeyPath:ofObject:change:context: 在被觀察的key path的值變化時(shí)調(diào)用.

.dealloc 停止觀察

static NSString *const KVO_CONTEXT_ADDRESS_CHANGED = @"KVO_CONTEXT_ADDRESS_CHANGED"

@implementation PersonWatcher

-(void)watchPersonForChangeOfAddress:(Person *)p

{? ??

// this begins the observing

[p addObserver:self

forKeyPath:@"address"

options:0

context:KVO_CONTEXT_ADDRESS_CHANGED];

// keep a record of all the people being observed,

// because we need to stop observing them in dealloc

[m_observedPeople addObject:p];


}

// whenever an observed key path changes, this method will be called

- (void)observeValueForKeyPath:(NSString *)keyPath

ofObject:(id)object

change:(NSDictionary *)change

context:(void*)context

{

// use the context to make sure this is a change in the address,

// because we may also be observing other things

if(context == KVO_CONTEXT_ADDRESS_CHANGED) {

NSString *name = [object valueForKey:@"name"];

NSString *address = [object valueForKey:@"address"];

NSLog(@"%@ has a new address: %@", name, address);

}

}

-(void) dealloc;

{

// must stop observing everything before this object is

// deallocated, otherwise it will cause crashes

for(Person *p in m_observedPeople){

[p removeObserver:self forKeyPath:@"address"];

}

[m_observedPeople release];

m_observedPeople = nil;

[super dealloc];

}

-(id) init;

{

if(self = [super init]){

m_observedPeople = [NSMutableArraynew];

}

returnself;

}

@end

這就是 KVO 的作用,它通過 key path 觀察對(duì)象的值,當(dāng)值發(fā)生變化的時(shí)候會(huì)收到通知。

一、KVO介紹

KVO就是觀察者模式,說白了就是你關(guān)心的一個(gè)值改變了,你就會(huì)得到通知。你就可以在你想處理的地方處理這個(gè)值。

二、KVO的使用

一般分為三步:

注冊監(jiān)聽

使用方法:

/***? 添加KVO監(jiān)聽者**@param observer 觀察者(監(jiān)聽器)*@param keyPath? 屬性名(要觀察的屬性)*@param options*@param context? 傳遞的參數(shù)*/- (void)addObserver:(NSObject*)observer forKeyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context;

例子:

//為對(duì)象p添加一個(gè)觀察者(監(jiān)聽器)

[p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"test"];

2.設(shè)置監(jiān)聽事件

/***

當(dāng)利用KVO監(jiān)聽到某個(gè)對(duì)象的屬性值發(fā)生了改變,就會(huì)自動(dòng)調(diào)用這個(gè)

**@param keyPath

哪個(gè)屬性被改了*@param object? 哪個(gè)對(duì)象的屬性被改了*@param change? 改成咋樣*@param context 當(dāng)初addObserver時(shí)的context參數(shù)值*/

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context{??

NSLog(@"%@ %@ %@ %@", object, keyPath, change, context);

}

3.取消監(jiān)聽

//釋放KVO監(jiān)聽-(void)dealloc{? ? [premoveObserver:selfforKeyPath:@"test"];

}

這些都是網(wǎng)上摘抄自己跟著敲了一遍溫習(xí)了一下,練習(xí)代碼KVC???? KVO??

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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