iOS--KVC

一直在使用一些方法好比在給模型賦值時使用的setValuesForKeysWithDictionary:jsonObject、改變一些屬性時valueForKeyPath等。但面試的時候,面試官一句給我說一個應用場景。我靠,當時我想吃土。結果是固然回答的很差,固然我會使用KVC,我也知道它,但我不能駕馭KVC。前端

有個觀點我很認同,咱們作前端的只要會用知道怎麼用怎麼搭建出界面就行,這樣咱們的任務就完成。可是若是知道運行原理,咱們能做出更好的App。就好比組裝車的若是知道發動機和剎車運行機制,那麼他就能組出性能更棒的車,也能避免好多問題。面試

a、介紹json

咱們能夠用KVC直接使用字符串訪問成員變量,而不使用setter或者getter方法。緣由是KVC提供了一種在編譯時動態訪問對象屬性和成員變量的方法。它很靈活但同時也失去了在編譯期間的檢查,若是有錯咱們也只能在運行時發現,好比經過使用valueForKeyPath訪問一個屬性或者其它時,只用當真正運行此處的時候咱們才能發現是否有此屬性。api

b、注意點數組

  1. valueForKey:以字符串調用對象的get屬性方法,或者讀取成員變量的值;setValue:forKey:以字符串調用對象的set屬性方法,或者修改爲員變量的值。
  2. 對於基本數據類型,KVC方法會對基本數據類型進行封裝(基本數據類型封裝爲NSNumber,其餘結構體類型封裝爲NSValue)。好比int型,valueForKey:方法返回的是NSNumber對象,須要再調用intValue取出其中的值。setValue:forKey:方法與之相似,接收NSNumber參數。
  3. 在使用KVC時,若是找不到字符串對應的屬性和成員變量時會怎麼樣?此時會調用valueForUndefinedKey:或者setValue:forUndefinedKey:這兩個方法,默認狀況下會拋出異常。通常我本身在模型對象中會重寫這兩個方法,由於當模型對象中的屬性名稱和後臺返回的json裏面某些數據名稱不同時,能夠很方便的檢測出,也能防止崩潰。
  4. 默認狀況下KVC方法可以直接訪問類的私有成員變量(就上面那個面試,我在苦思冥想以後說KVC能夠訪問到私有變量,可是面試官一句那要私有幹嗎。呃  我當時想,完了  無法玩了  徹底不在一個等級上),也能夠重寫accessInstanceVariablesDirectly方法,並令其返回NO(默認是返回YES)。KVC方法定義在NSKeyValueCoding類別中,該類別附加於NSObject類上,因此全部對象都具備這些方法。在此,反正我不提倡訪問私有變量,就如哪位面試官說的。聲明私有表明不想被訪問到,咱們若是這樣幹不是逆天而行嗎?若是真的在外部使用到此變量,它仍是私有的,大多數狀況下只能說明咱們本身的設計有問題,固然也有例外。
  5. 在一些特殊的類的對象上調用KVC方法會有特別的效果。對於數組NSArray、集合NSSet,調用valueForKey:會對每一個數組和集合成員調用valueForKey:,並返回新的數組或者集合。如咱們須要把一個數組裏面的字符串取出來將首字母大寫,並將新的字符串存到新數組中咱們可使用KVC很方便的達到需求

      [array valueForKeyPath:@「str.capitalizedString」];性能

valueForKeyPath稱爲鍵值鏈(Key Path)。鍵值鏈是用點將若干鍵相連的字符串,經過在對象上調用valueForKeyPath:或者setValue:forKeyPath:。學習

c、乾貨設計

KVC有些東西常常被忽略掉,可是很使用的小技巧。對象

我對於KVC嵌套知識點學習自一篇簡書,感受人家整理的很棒,先感謝人家,在此就厚顏無恥的引用下。字符串

文/水瓶座_iOSer(簡書做者)

原文連接:http://www.jianshu.com/p/a6a0abac1c4a

獲取數組裏的,最大、最小、平均、求和

NSArray *array = @[@"10",@"35",@72,@78,@"1"]; 

NSNumber *sum = [array valueForKeyPath:@"@sum.floatValue"]; 

NSNumber *avg = [array valueForKeyPath:@"@avg.floatValue"]; 

NSNumber *max = [array valueForKeyPath:@"@max.floatValue"]; 

NSNumber *min = [array valueForKeyPath:@"@min.floatValue"];  

刪除重複數據

NSArray *array = @[@"name", @"w", @"aa", @"zxp", @"aa"]; //返回的是一個新的數組

 NSArray *newArray = [array valueForKeyPath:@"@distinctUnionOfObjects.self"]; 

NSLog(@"%@", newArray);

一樣能夠嵌套使用,先剔除name對應值的重複數據再取值

NSArray *array = @[ @{@"title":@"zxp",@"name":@"zhangxiaoping"}, @{@"title":@"zxp2",@"name":@"zhangxiaoping2"}, @{@"title":@"zxp",@"name":@"zhangxiaoping3"}, @{@"title":@"zxp",@"name":@"zhangxiaoping"}];

//根據name字段,來進行重複刪除。

NSArray *newArray = [array valueForKeyPath:@"@distinctUnionOfObjects.name"];

//若是要根據title字段來刪除重名的寫法爲`@distinctUnionOfObjects.title` 

NSLog(@"%@", newArray);

/*

print:( zhangxiaoping3, zhangxiaoping2, zhangxiaoping)是一個字符串數組*/

進行實例方法的調用

NSArray *array = @[@"name", @"w", @"aa", @"ZXPing"]; 

NSLog(@"%@", [array valueForKeyPath:@"uppercaseString"]);

至關於數組中的每一個成員執行了uppercaseString方法,而後把返回的對象組成一個新數組返回。既然能夠用uppercaseString方法,那麼NSString的其餘方法也能夠,好比[array valueForKeyPath:@「length"]。固然,其餘對象的實例方法也能夠以此類推來進行調用。

相關文章
相關標籤/搜索