iOS基礎(chǔ)(四) - KVC和KVO

iOS觀察者模式學(xué)習(xí)

(1)KVC與KVO簡(jiǎn)介

  • KVC

KVC(Key-value coding)是一種間接更改對(duì)象狀態(tài)的方式。

官方文檔描述:

Key-value coding is a mechanism for accessing an object’s properties indirectly, using strings to identify properties, rather than through invocation of an accessor method or accessing them directly through instance variables. In essence, key-value coding defines the patterns and method signatures that your application’s accessor methods implement.

  • KVC的作用

通過(guò)鍵值的方式訪問(wèn)對(duì)象或者修改對(duì)象的值

比如:NSString *name = [car valueForKey: @"name"];通過(guò)-valueForKey:獲取對(duì)象,它會(huì)先查找以參數(shù)名命名(格式為-key或-isKey)的getter方法,對(duì)于上面的調(diào)用,valueForKey:會(huì)先尋找-name方法。如果沒(méi)有這樣的getter方法,它將會(huì)在對(duì)象內(nèi)尋找名稱格式為_key或key的實(shí)例變量。通過(guò)使用KVC,沒(méi)有相關(guān)getter方法也能獲取對(duì)象,不需要通過(guò)對(duì)象指針來(lái)直接訪問(wèn)實(shí)例變量。

  • KVC的優(yōu)缺點(diǎn)

1.KVC可以輕松處理集合類。(如:NSArray)

2.KVC沒(méi)有相關(guān)getter方法也能獲取對(duì)象,不需要通過(guò)對(duì)象指針來(lái)直接訪問(wèn)實(shí)例變量

3.簡(jiǎn)化代碼

4.KVC需要解析字符串,速度比較慢

5.編譯器無(wú)法進(jìn)行錯(cuò)誤檢查

  • KVO

KVO(Key-value Observing)是基于KVC的,一種監(jiān)聽(tīng)方式,也就是所謂的觀察者模式。

官方文檔描述:

Key-value observing provides a mechanism that allows objects to be notified of changes to specific properties of other objects. It is particularly useful for communication between model and controller layers in an application.

(2)KVC代碼實(shí)現(xiàn)

//1.setValue: forKey
[car setValue: @"奔馳" forKey: @"name"];
[car setValue: [NSNumber numberWithFloat: 80] forKey: @"speed"];
[car setValue: @"黑色" forKey: @"carPaint"];

//1.valueForKey
NSString *name = [currentCar valueForKey: @"name"];
NSNumber *speed = [currentCar valueForKey: @"speed"];
NSString *carPaint = [currentCar valueForKey: @"carPaint"];

//2.setValue:forKeyPath
[car setValue: [NSNumber numberWithFloat: 40] forKeyPath: @"engine.horsepower"];
self.showCarDetail.text = [self showCarDetail: car];

//2.valueForKeyPath
NSNumber *horsepower = [currentCar valueForKeyPath: @"engine.horsepower"];

//3.整體操作:訪問(wèn)數(shù)組,如果使用某個(gè)鍵值來(lái)訪問(wèn)一個(gè)NSArray數(shù)組,它實(shí)際上會(huì)查詢相應(yīng)數(shù)組中的每個(gè)對(duì)象,然后將查詢結(jié)果大包到另一個(gè)數(shù)組并返回,但是不能直接在建路徑中索引這些數(shù)組,如:tires[0].pressure
NSArray *pressures = [currentCar valueForKeyPath: @"tires.pressure"];
NSLog(@"%@", pressures);

//4.快速運(yùn)算@count,@sum,@avg,@min,@max,@distinctUnionOfObjects
NSNumber *count = [currentCar valueForKeyPath: @"tires.@count"];    //對(duì)左邊鍵值返回?cái)?shù)組操作,獲取數(shù)組數(shù)量
NSNumber *sum = [currentCar valueForKeyPath: @"tires.@sum.pressure"];    //對(duì)左邊鍵值返回?cái)?shù)組操作,獲取每個(gè)數(shù)組里面的pressure值,求和
NSNumber *avg = [currentCar valueForKeyPath: @"tires.@avg.pressure"];    //對(duì)左邊鍵值返回?cái)?shù)組操作,獲取每個(gè)數(shù)組里面的pressure值,求平均值
NSNumber *min = [currentCar valueForKeyPath: @"tires.@min.pressure"];    //對(duì)左邊鍵值返回?cái)?shù)組操作,獲取每個(gè)數(shù)組里面的pressure值,找出最小值
NSNumber *max = [currentCar valueForKeyPath: @"tires.@max.pressure"];    //對(duì)左邊鍵值返回?cái)?shù)組操作,獲取每個(gè)數(shù)組里面的pressure值,找出最大值
NSArray *tireType = [currentCar valueForKeyPath: @"tires.@distinctUnionOfObjects.pressure"];    //對(duì)左邊鍵值返回?cái)?shù)組操作,獲取每個(gè)數(shù)組里面的pressure值,去掉重復(fù)的值,返回一個(gè)包含所有不重復(fù)值的數(shù)組
NSLog(@"TiresCount: %@ Sum: %@, Avg: %@, Min: %@, Max: %@, TireType: %@", count, sum, avg, min, max, tireType);

//5.批處理
//字典里面不能為nil,如果返回值有nil,則KVC會(huì)自己處理,將返回[NSNull null]表示nil
//<null>和(null)的區(qū)別:前者是[NSNull null]對(duì)象,而后者是正真的nil。
NSArray *keys = [NSArray arrayWithObjects: @"make", @"modelYear", @"numberOfDoors", nil];
NSDictionary *carValues = [currentCar dictionaryWithValuesForKeys: keys];
NSLog(@"%@", carValues);
    
//6.nil處理
//可以自己運(yùn)行一下,重寫和沒(méi)有重寫setNilValueForKey:方法的代碼
[currentCar setValue: nil forKey: @"speed"];
NSLog(@"carSpeed: %@", [currentCar valueForKey: @"speed"]);
    
//7.處理未定義的值
[currentCar setValue: [NSNumber numberWithFloat: 1500] forKey: @"mileage"];
[currentCar setValue: [NSNull null] forKey: @"price"];
[currentCar setValue: nil forKey: @"capacity"];
NSLog(@"Mileage: %@ Price: %@, Capacity: %@", [currentCar valueForKey: @"mileage"], [currentCar valueForKey: @"price"], [currentCar valueForKey: @"capacity"]);

//8.KVC有自動(dòng)裝箱的功能,當(dāng)使用valueForKey時(shí),它自動(dòng)將標(biāo)量值(int,float,struct...)放入NSNumber或NSValue中;當(dāng)使用setValueForKey,它自動(dòng)將標(biāo)量值從這些對(duì)象取出。

(3)KVO代碼實(shí)現(xiàn)

//應(yīng)該在監(jiān)聽(tīng)者里添加監(jiān)聽(tīng),而不是在被監(jiān)聽(tīng)者里添加監(jiān)聽(tīng)
//在被監(jiān)聽(tīng)者添加監(jiān)聽(tīng)會(huì)造成循環(huán)引用的問(wèn)題
car = [[Car alloc] init];
[car addObserver: self forKeyPath: @"carPaint" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context: nil];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([keyPath isEqualToString: @"carPaint"]) {
        NSLog(@"%@", [change objectForKey: @"new"]);    //修改之后的值
        self.showCarDetail.text = [NSString stringWithFormat: @"車的顏色是%@", [change objectForKey: @"new"]];
    }
}

- (void)dealloc {
    //監(jiān)聽(tīng)者應(yīng)該是self,被監(jiān)聽(tīng)者是car
    [car removeObserver: self forKeyPath: @"carPaint"];
}

(4)Demo展示:


Observer.gif

Demo下載

最后編輯于
?著作權(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)容

  • 官方文檔點(diǎn)這里:Key-Value Coding Programming Guide、NSKey?Value?Co...
    阿斯蘭iOS閱讀 1,732評(píng)論 0 1
  • KVO與KVC簡(jiǎn)單理解 ///////////////////////////////////////我是該死的分...
    李某lkb閱讀 481評(píng)論 0 1
  • KVC 與 KVO 是 Objective C 的關(guān)鍵概念,個(gè)人認(rèn)為必須理解的東西,下面是實(shí)例講解。 (一)Key...
    Asserts閱讀 273評(píng)論 0 0
  • 3月6日,馬刺隊(duì)104-94擊敗國(guó)王隊(duì)取得8連勝,并豪取主場(chǎng)開季30連勝,這是NBA歷史上第三支在開季以來(lái)主場(chǎng)連續(xù)...
    zoneball閱讀 1,122評(píng)論 4 8
  • 上班路上,走到平常經(jīng)過(guò)的大榕樹旁邊,發(fā)現(xiàn)地面上鋪了一層薄薄的落葉,抬頭一看,發(fā)現(xiàn)還有一些黃葉正依依不舍地離開曾經(jīng)依...
    依心隨行閱讀 364評(píng)論 1 1

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