ios中key-value coding (kvc)俗稱鍵值編碼,是乙個非正式的協議,它提供一種機制來間接訪問物件的屬性。
直接訪問物件是通過呼叫訪問器的方法實現,而kvc不需要呼叫訪問器的設定和獲取方法,可以直接訪問物件的屬性。
kvc的操作方法由nskeyvaluecoding協議提供,而nsobject就實現了這個協議,也就是說objc中幾乎所有的物件都支援kvc操作,
常用的kvc操作方法如下:
1)對屬性賦值(動態設定):
setvalue:屬性值 frkey:屬性名(用於簡單路徑);
setvalue:屬性值 forkeypath:屬性路徑(用於復合路徑,例如person有乙個account型別的屬性,那麼person.account就是乙個復合屬性);
kvc的一般用法:
setvalue:屬性值 forkey:屬性名和valueforkey:屬性名
- (void)viewdidload
#pragma mark --setvalue:屬性值 forkey:屬性名
-(void)test1
輸出結果:
2)對屬性取值(動態讀取):
valueforkey:屬性名 (用於簡單路徑);
valueforkeypath:屬性名(用於復合路徑);
setvalue:屬性值 forkeypath:屬性路徑和valueforkeypath:屬性名(用於復合路徑)
- (void)viewdidload
#pragma mark --setvalue:屬性值 forkeypath:屬性路徑和valueforkeypath:屬性名(用於復合路徑)
-(void)test2
輸出結果:
注意:(1). key的值必須正確,如果拼寫錯誤,會出現異常
1> * 首先去接收者(呼叫方法的那個物件)的類中查詢與key相匹配的訪問器方法(-set),如果找到了乙個方法,就檢查它引數的型別,如果它的引數型別不是乙個物件指標型別,但是只為nil,就會執行setnilvalueforkey:方法,setnilvalueforkey:方法的預設實現,是產生乙個nsinvalidargumentexception的異常,但是你可以重寫這個方法.
* 如果方法引數的類是乙個物件指標型別,就會簡單的執行這個方法,傳入對應的引數.如果方法的引數型別是nsnumber或nsvalue的對應的基本型別,先把它轉換為基本資料類,再執行方法,傳入轉換後的資料.
2> * 如果沒有對應的訪問器方法(setter方法),如果接受者的類的+accessinstancevariablesdirectly方法返回yes,那麼就查詢這個接受者的與key相匹配的例項變數(匹配模式為_,_is,,is):比如:key為age,只要屬性存在_age,_isage,age,isage中的其中乙個就認為匹配上了,如果找到這樣的乙個例項變數,並且的型別是乙個物件指標型別,
3> * 首先released物件上的舊值,然後把傳入的新值retain後的傳入的值賦值該成員變數,如果方法的引數型別是nsnumber或nsvalue的對應的基本型別,先把它轉換為基本資料類,再執行方法,傳入轉換後的資料.
* 如果訪問器方法和例項變數都沒有找到,執行setvalue:forundefinedkey:方法,該方法的預設實現是產生乙個nsundefinedkeyexception型別的異常,但是我們可以重寫setvalue:forundefinedkey:方法
(2). 當key的值是沒有定義的,valueforundefinedkey:這個方法會被呼叫,如果你自己寫了這個方法,key的值出錯就會呼叫到這裡來
(3). 因為類key反覆巢狀,所以有個keypath的概念,keypath就是用.號來把乙個乙個key鏈結起來,這樣就可以根據這個路徑訪問下去
(4).nsarray/nsset等都支援kvc
3)key值找不到時,異常處理
使用kvc時,如果**中的key值不存在,會丟擲異常,可以在類中通過重寫它提供
- (void)setvalue:(id)value forundefinedkey:(nsstring *)key
當key不存在時,會自動呼叫上面的這個方法,可以在這個方法中進行處理
- (void)setvalue:(id)value forundefinedkey:(nsstring *)key
4)kvc的字典轉模型和模型轉字典
1>字典轉模型
當我們需要把json字串反序列化成我們想要的物件 ,可以通過下面的方法
- (void)setvaluesforkeyswithdictionary:(nsdictionary*)keyedvalues
- (id)initwithdictionary:(nsdictionary *)dictionary
return self;
}
注意:字典中的key 和物件屬性要求一樣
2>模型轉字典
- (nsdictionary *)dictionarywithvaluesforkeys:(nsarray *)keys;
nsdictionary *dic = [self.dataarray dictionarywithvaluesforkeys:@[@"name",@"age"]];
for (int i =0 ; i5)總結
1)kvc需要把字串屬性名稱轉換後才能賦值,呼叫的set方法,效能消耗較高
2)kvc查詢乙個屬性進行讀取的一般順序
1>動態設定屬性,
優先考慮呼叫seta方法,如果沒有該方法則優先考慮搜尋成員變數_a,如果仍然不存在則搜尋成員變數a,如果最後仍然沒搜尋到則會呼叫這個類的setvalue:forundefinedkey:方法(注意搜尋過程中不管這些方法、成員變數是私有的還是公共的都能正確設定);
2>動態讀取屬性
優先考慮呼叫a方法(屬性a的getter方法),如果沒有搜尋到則會優先搜尋成員變數_a,如果仍然不存在則搜尋成員變數a,如果最後仍然沒搜尋到則會呼叫這個類的valueforundefinedkey:方法(注意搜尋過程中不管這些方法、成員變數是私有的還是公共的都能正確讀取);
3>解析的資料 型別不確定處理
-(void)setvalue:(id)value forkey:(nsstring *)keyelse
}
別忘加上這個,也要重寫(未被定義的不做處理):
-(void)setvalue:(id)value forundefinedkey:(nsstring *)key
iOS開發之UI基礎 KVC
k vc key value coding 1.字典轉模型 dic answer dic icon dic title dic options kvc 把字典中的值,賦給當前物件制定的屬性 answer self setvalue dic answer forkeypath answer 遍歷字典中...
Objective C語法之Category的使用
無論乙個類設計的如何完美,都不可避免的會遇到沒有 到的需求,那怎麼擴充套件現有的類呢?當然,繼承是個不錯的選擇。但是objective c提供了一種特別的方式來擴充套件類,叫catagory,可以動態的為已經存在的類新增新的行為。這樣可以保證類的原原來的基礎上,較小的改動就可以增加需要的功能。使用c...
Objective C語法之Category的使用
無論乙個類設計的如何完美,都不可避免的會遇到沒有 到的需求,那怎麼擴充套件現有的類呢?當然,繼承是個不錯的選擇。但是objective c提供了一種特別的方式來擴充套件類,叫catagory,可以動態的為已經存在的類新增新的行為。這樣可以保證類的原原來的基礎上,較小的改動就可以增加需要的功能。使用c...