字典的KVC與setObject:forKey:,你瞭解多少?

我們在初始化一個可變字典之後,再給其添加鍵值對的時候可以使用字典的setObject:forKey:方法,或者使用kvc的方式。

setObject:forKey:

將給定的鍵值對添加到字典中

- (void)setObject:(ObjectType)anObject forKey:(id<NSCopying>)aKey

參數講解:

anObject:

aKey的值,對該對象的強引用由字典維護

重點: 如果anObject爲nil的話,會拋出NSInvalidArgumentException異常,如果你想在字典中表示一個nil 值,可以使用 NSNull

比如:
[dict setObject:[NSNull null] forKey:@"null"];

打印:null = "<null>";

aKey:

valuekey,aKey將被複制(使用copyWithZone:方法;key必須遵守NSCopying協議),如果字典中存在了該key,將替換anObject

重點: 如果key爲nil的話,會拋出NSInvalidArgumentException異常

也就是使用setObject:forKey:方法會對value強引用,會使value的引用計數加一。

    NSMutableDictionary *dict = @{}.mutableCopy;
    NSString *key = @"test";
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    
    printf("after init retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(arr)));
    
    [dict setObject:arr forKey:key];
    
    printf("after setObject:forKey: retain count = %ld\n ",CFGetRetainCount((__bridge CFTypeRef)(arr)));

打印信息:

after init retain count = 1
after setObject:forKey: retain count = 2

字典的KVC

使用KVC的方式也可以爲一個可變字典添加一個鍵值對,

- (void)setValue:(nullable ObjectType)value forKey:(NSString *)key;

value

可以爲nil,當valuenil時,會調用字典的removeObjectForKey:方法,不爲nil時,調用字典的setObject:forKey:方法來添加鍵值對

key:

需要注意的是,當使用kvc的時候,key必須是字符串

kvc在引用計數環境下,直接訪問實例變量的話,value會被retain,

    NSMutableDictionary *dict = @{}.mutableCopy;
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    
    printf("after init retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(arr)));
    
    [dict setObject:arr forKey:@"test"];
    
    printf("after setObject:forKey: retain count = %ld\n ",CFGetRetainCount((__bridge CFTypeRef)(arr)));
    
    // kvc 方式添加鍵值對
    [dict setValue:arr forKey:@"test2"];
    
    printf("after kvc retain count = %ld\n ",CFGetRetainCount((__bridge CFTypeRef)(arr)));

打印:

after init retain count = 1
after setObject:forKey: retain count = 2
after kvc retain count = 3

總結:
相同點:

  1. 兩個方法的key都不能爲nil,否則拋出NSInvalidArgumentException
  2. 都會對value強引用

不同點

  1. setObjec:forKey:key必須遵守NSCopying協議,KVC的key必須爲字符串
  2. setObjec:forKey:value不能爲空,否則會拋出NSInvalidArgumentException異常; KVC的value會nil時,會調用字典的removeObjectForKey:方法,否則,調用字典的setObject:forKey:方法添加鍵值對

取值

相應的,我們從字典中取值的時候,可以使用字典的objectForKey :方法,也可以使用valueForKey:方法。

這兩種方法都比較簡單,一般情況下,字典的valueForKey:方法也是調用objectForKey :來取值的,但這存在了一個前提:key不能以字符"@"開頭

key不是以"@"開始時,調用字典的objectForKey:方法。如果以"@"開始的話,則去除掉"@"字符,並用剩餘的字符調用[super valueForKey:]方法。當父類也沒有找到該key時,會調用valueForUndefinedKey:方法,而valueForUndefinedKey:默認是拋出一個異常的。(只會去除開頭的第一個"@",即如果key是以多個"@"字符開始的話,只會去除第一個開始的"@",剩餘的"@"字符會被保留)

    NSMutableDictionary *dict = @{}.mutableCopy;
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    NSString *key1 = @"@@@test";
    [dict setObject:arr forKey:key1];
    //取值
    id test2 = [dict valueForKey:key1];

控制檯打印:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSDictionaryM 0x600000222a80> valueForUndefinedKey:]: this class is not key value coding-compliant for the key @@test.'

可以看到,我們本來是通過"@@@test"字符串作爲key去取值的,但是在查找過程中去除了第一個"@"字符,用剩下的字符串"@@test"去作爲key去查找的(不是把所有的"@"字符去除)。

另外,與賦值時不同,取值時keynil時並不會拋出異常。

刪除

字典可以使用removeObjectForKey :方法刪除某個鍵值對

- (void)removeObjectForKey:(KeyType)aKey;

key爲nil的話, 會拋出NSInvalidArgumentException異常
當字典中不存在該key的時候,則什麼都沒做。

removeAllObjects
清空字典裏的數據,其實是向字典中每個key以及對應的value發送release消息

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章