1. 程式人生 > >iOS -setValue:forKey:和-setObject: forKey區別

iOS -setValue:forKey:和-setObject: forKey區別

首先看一下下面的程式碼,請問程式是否會崩潰?如果不會,那麼輸出結果應該是什麼?

NSMutableDictionary * dic = [@{@"name":@"小明"} mutableCopy];
[dic setObject:@"Men" forKey:@"gender"];
[dic setValue:nil forKey:@"gender"];
NSLog(@" -- %@ -- ",dic);

既然問到了輸出結果,如果你不是很確定答案的話,應該可以猜出來程式是不會崩潰的。
下面就打個斷點來看dic走完每一行程式碼後的結果:
這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

-setValue: forKey: 是KVC(鍵-值編碼)提供的方法,旨在通過key去修改一個obj的屬性,如果是字典的話,則修改key對應的value,如果是陣列或者集合,則會向每個物件傳送此訊息,去修改元素的key對應的property。
說到這裡就不得不提一下:如果向一個物件a傳送-satValue: forKey:訊息,除非能確保a包含key對應的property(即key和A的某個property名字相同),否則必須實現類A或者其父類的-setValue: forUndefinedKey:方法,否則會導致crash。

/* Send -setObject:forKey: to the receiver, unless the value is nil, in which case send -removeObjectForKey:.
*/
- (void)setValue:(nullable ObjectType)value forKey:(NSString *)key;

按照其註釋:給訊息接受者傳送-setObject:forKey: 訊息,如果value為nil,則給訊息接受者傳送-removeObjectForKey:訊息。

-setObject: forKey: 是NSMutableDictionary的物件方法,旨在通過去修改字典中key對應的value,如果key不存在,則新增此key-value對。
值得注意的是,為了使你的程式更加strong,當你呼叫-setObject: forKey:時,務必對object進行判空,只有當object不為nil時方可呼叫該方法,否則會導致程式crash。
這裡寫圖片描述

    NSMutableDictionary * dic = [@{@"name":@"小明"} mutableCopy];
    //_gender是一個全域性變數
    //當_gender為nil時,執行到此將會crash
//    [dic setObject:_gender forKey:@"gender"];
    //為避免此類crash,需要對_gender進行判空,如此就不會crash了,只是你從字典裡可能得不到想要的資訊,與crash相比,此舉的使用者體驗要比crash強得太多了
    if (_gender) [dic setObject:_gender forKey:@"gender"
];

總結一下吧
相同點:

  • 二者都可以對可變字典進行修改;

不同點:

  • -setValue:forKey:是KVC提供的方法,可對絕大部分物件進行操作(包括自定義物件),-setObject: forKey是NSMutableDictionary提供的方法,只能操作可變字典;
  • -setValue:forKey:當value為nil時,對於字典相當於刪除key-value對,-setObject: forKey當object為nil時將直接導致程式crash,因此呼叫之前需要判空;