核心概念
- 鍵值對:Key 唯一,Value 可重複
- Key 通常用
NSString,也可用任何實現 NSCopying 的對象
- Key/Value 不能為 nil,需用
[NSNull null] 佔位
- NSDictionary 不可變;NSMutableDictionary 可變
NSDictionary 不可變字典
創建
// 單鍵值
NSDictionary *d1 = [NSDictionary dictionaryWithObject:val1 forKey:@"key1"];
// 多鍵值 (以 nil 結尾)
NSDictionary *d2 = [NSDictionary dictionaryWithObjectsAndKeys:
val1, @"key1", val2, @"key2", nil];
// 現代字面量語法 (推薦)
NSDictionary *d3 = @{
@"name": @"Jack",
@"age": @25,
@"city": @"Beijing"
};
// 從文件 (plist)
NSDictionary *d4 = [NSDictionary dictionaryWithContentsOfFile:path];
查詢
NSUInteger count = [d3 count]; // 鍵值對數
id value = [d3 objectForKey:@"name"]; // 取值 (不存在返回 nil)
NSArray *keys = [d3 allKeys]; // 所有鍵 (順序不定)
NSArray *values = [d3 allValues]; // 所有值
NSEnumerator *keyEnum = [d3 keyEnumerator]; // 鍵迭代器
NSMutableDictionary 可變字典
創建
NSMutableDictionary *md = [NSMutableDictionary dictionary];
NSMutableDictionary *md2 = [NSMutableDictionary dictionaryWithCapacity:10];
NSMutableDictionary *md3 = [NSMutableDictionary dictionaryWithDictionary:d3];
修改操作
// 設置/更新鍵值
[md setValue:@"newVal" forKey:@"key"];
[md setObject:@"objVal" forKey:@"key"]; // 等價
// 批量合併
[md addEntriesFromDictionary:otherDict];
// 刪除
[md removeObjectForKey:@"key"]; // 刪單個
[md removeObjectsForKeys:@[@"k1", @"k2"]]; // 批量刪除
[md removeAllObjects]; // 清空
遍歷方式對比
| 方式 | 代碼 | 特點 |
| 快速枚舉 (推薦) | for (id key in dict) { id v = dict[key]; } | 語法最簡潔,效率高 |
| 鍵數組 + 下標 | for (id key in [dict allKeys]) { id v = [dict objectForKey:key]; } | 可控制順序(排序keys) |
| 迭代器 | NSEnumerator *en=[dict keyEnumerator]; while(key=[en nextObject]) | 舊式 API |
| Block 遍歷 | [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){}] | 同時得鍵值,支持提前終止 |
KVC / KVO 整合
// KVC 批量設置
[dict setValuesForKeysWithDictionary:@{@"a": @1, @"b": @2}];
// KVC 取值
id val = [dict valueForKey:@"name"]; // 等同 objectForKey:
// KVO 觀察字典變化 (需可變字典)
[md addObserver:self forKeyPath:@"key" options:NSKeyValueObservingOptionNew context:nil];
// 當 md[@"key"] 變化時觸發 observeValueForKeyPath:ofObject:change:context:
NSNull 佔位符
// 存儲「無值」語義
[md setObject:[NSNull null] forKey:@"optionalField"];
// 取值時判斷
id v = md[@"optionalField"];
if (v == [NSNull null] || v == nil) { /* 無值 */ }
性能與最佳實踐
- 哈希表實現,查找/插入/刪除平均 O(1)
- Key 必須實現
copyWithZone: (NSCopying),字典內部拷貝 Key
- 自定義 Key 類:必須實現
isEqual: 和 hash,相等對象哈希值必相等
- 大量數據預知規模:
dictionaryWithCapacity:
- 只讀場景用
NSDictionary + 字面量,線程安全
- 避免在循環中頻繁
setObject:forKey:,批量用 addEntriesFromDictionary:
常見陷阱
- 以為 Key 可為 nil → 崩潰
- 修改字典同時快速枚舉 → 運行時異常
NSGenericException
- 用可變對象作 Key 且修改其狀態 → 查找失效 (哈希值變化)
objectForKey: 返回 nil 可能是「不存在」或「值為 NSNull」,需區分