需求一:將字典轉換成自己需的對象,對象的屬性是字典的key值,直接使用key值獲取數據存在兩個缺點,一是key值難以記憶,二是直接使用key值Xcode不會有智能提示,很容易導致未知的錯誤。使用模型時,可以直接通過點語法將需要的數據點出,保證數據準確無誤。使用模型的優點還在於存儲、傳值都比較方便,不 ...
需求一:將字典轉換成自己需的對象,對象的屬性是字典的key值,直接使用key值獲取數據存在兩個缺點,一是key值難以記憶,二是直接使用key值Xcode不會有智能提示,很容易導致未知的錯誤。使用模型時,可以直接通過點語法將需要的數據點出,保證數據準確無誤。使用模型的優點還在於存儲、傳值都比較方便,不容易出錯。最主要的是這也符合我們MVC和MVVM的設計模式。
註意:要使用模型就離不開KVC,假如我們從外界傳入一個字典,字典中有兩個 key對應的值是我們需要的,這兩個值分別是 “name”、“age”。要使用KVC的時候要註意模型的屬性一定要和字典中的key值相對應。比如字典中的“name”,那模型中就必須有一個name的屬性。這樣就可以使用KVC了,KVC的兩種方法:(下文都預設我們有兩個模型屬性,分別是name和age,傳入的字典預設為dict)
1. setValue(模型屬性, forKey:字典的key值)
eg:setValue(self.name, forKey:dict[“name”])
*這種賦值方法很麻煩,每需要一個key值就要打一遍該方法。這樣的賦值方式就和self.name = dict[“name”] 的區別不是太大
2. setValuesForKeysWithDictionary(傳入的字典)
eg: setValuesForKeysWithDictionary(dict)
*直接完成賦值,其實setValuesForKeysWithDictionary(傳入的字典),它預設也是調用setValue(模型屬性, forKey:字典的key值 ),遍歷字典一一給模型屬性賦值。所以使用KVC時就要求模型的屬性必須喝字典的key值一一對應。
需求二:如果我們只想使用字典中的部分值呢?一個大字典,裡面有好幾十個key,難道我們還要在模型中根據key值定義幾十個屬性麽?當然我們程式猿都是很懶的,肯定不會定義這麼多key值的,此時我們只需重寫KVC的以下方法就行了:
3.setValue(value: AnyObject?, forUndefinedKey key: String)
*這個方法會幫我們過濾我們沒有的key值,值執行 setValuesForKeysWithDictionary(dict)時,當監測出我們沒有字典中key值所對應的屬性時就會調用這個方法。
*重寫時裡面不需要寫任何代碼,如果想列印哪些key值我們沒有時就可以在裡面列印。
需求三:我們知道很多字典中都有“id”這個key值。而“id”在我們iOS中是個數據類型,顯然不能將“id”當作模型屬性名稱去定義。此時我們只需要隨意定義一個屬性名去保存“id”,當然為了更已讀、嚴謹一些,我們一般還是定義為“ID”最為恰當。而我們知道要使用KVC就要key值和模型名一一對應,但是我們就是想要獲取“id”。此時需要將“需求一”和“需求二”結合起來看了。我們在獲取“id”時,直接使用傳入的字典賦值:(此時我們新添一個屬性“ID”)
eg :self.ID = dict[“id”]
*當這樣賦值之後就取出”id “所對應的value了。
但是我們還要獲取其他的value呢,此時在使用 setValuesForKeysWithDictionary(dict)完成其他屬性的賦值。當然也需要重寫setValue(value: AnyObject?, forUndefinedKey key: String)方法,因為字典中並有“ID”這個key值(字典中是“id”,“ID”是模型新定義的屬性)。完整代碼如下 :
swift:
override init() {
super.init()
self.ID = dict[@"id”];
setValuesForKeysWithDictionary(dict)
}
override func setValue(value: AnyObject?, forUndefinedKey key: String) { }
OC:
+ (instancetype) testWithDict:(NSDictionary *)dict{
TEST *test = [[TEST alloc]init];
test.ID = dict[@"id"];
[test setValuesForKeysWithDictionary:dict];
return test;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
}
*註意當在對象方法使用KVC時一定要先super.init,因為要首先保證有一個對象存在,這樣才能訪問這個對象的屬性。
*註意在使用對象方法時,命名方法名時“With”中的“W”必須大寫,否則無法完成super.init
eg:- (instancetype) initWithDict:(NSDictionary *)dict
補充:KVC強大不僅僅只在於給模型賦值,KVC還可給只讀 屬性賦值,改變私有屬性。比如UITabBarController中tabBar是只讀屬性,用一般的賦值時無法給只讀屬性賦值的,但是通過
setValue(value,forKey:”屬性名”)
eg:setValue(value,forKey:“tabBar”)
總結:KVC是Set Value Coding的簡稱,它是一種直接通過字元串的名字(key)來訪問類屬性的機制。而不是通過Setter(設置器)和Getter(讀取器)。