純粋な NSMutableDictionary では不可能であり、ほとんどの場合、nil 値を辞書に変換する[NSNull null]
か、単に辞書から除外する必要があります。ただし、(ごくまれに) nil 値を許可すると便利な場合があり、そのような場合は、カスタム コールバックで CFMutableDictionary を使用できます。
このようにすれば、CFDictionarySetValue
や などのすべてのアクセスに CoreFoundation API を使用することをお勧めしますCFDictionaryGetValue
。
ただし、何をしているのかわかっている場合は、無料のブリッジングを使用して、その CFMutableDictionary を NSMutableDictionary または NSDictionary にキャストできます。これは、NSDictionary を受け入れるヘルパーがたくさんあり、それらを修正した nil 対応の辞書で使用したい場合に便利です。(もちろん、ヘルパーが nil 値に驚いていないことを確認してください。)
ブリッジングを行う場合は、次の点に注意してください。
1) NSMutableDictionary セッターは、ブリッジする前に nil 値でエラーを発生させるため、CFDictionarySetValue を使用して nil になる可能性のある値を設定する必要があります。
2) 技術的には、ここで NSMutableDictionary の契約に違反しており、問題が発生する可能性があります (たとえば、将来の OS アップデートで)
3) ディクショナリで nil 値を見つけると、多くのコードが非常に驚くでしょう。ブリッジされたフランケンディクショナリのみを、制御するコードに渡す必要があります
ブリッジされた CFDictionary が NSDictionary と異なる動作をする理由の説明については、無料のブリッジに関するとんでもない魚の投稿を参照してください。
例:
#import <Foundation/Foundation.h>
const void *NullSafeRetain(CFAllocatorRef allocator, const void *value) {
return value ? CFRetain(value) : NULL;
}
void NullSafeRelease(CFAllocatorRef allocator, const void *value) {
if (value)
CFRelease(value);
}
const CFDictionaryValueCallBacks kDictionaryValueCallBacksAllowingNULL = {
.version = 0,
.retain = NullSafeRetain,
.release = NullSafeRelease,
.copyDescription = CFCopyDescription,
.equal = CFEqual,
};
int main(int argc, const char * argv[])
{
@autoreleasepool {
CFMutableDictionaryRef cfdictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kDictionaryValueCallBacksAllowingNULL);
CFDictionarySetValue(cfdictionary, @"foo", @"bar");
CFDictionarySetValue(cfdictionary, @"boz", nil);
NSMutableDictionary *dictionary = CFBridgingRelease(cfdictionary);
NSLog(@"dictionary[foo] = %@", dictionary[@"foo"]);
NSLog(@"dictionary[foo] = %@", dictionary[[@"fo" stringByAppendingString:@"o"]]);
NSLog(@"dictionary[boz] = %@", dictionary[@"boz"]);
NSLog(@"dictionary = %@", dictionary);
NSLog(@"(dictionary isEqualTo: dictionary) = %d", [dictionary isEqualToDictionary:dictionary]);
}
return 0;
}
出力:
dictionary[foo] = bar
dictionary[foo] = bar
dictionary[boz] = (null)
dictionary = {
boz = (null);
foo = bar;
}
(dictionary isEqualTo: dictionary) = 1