NSMutableDictionary和NSCache (copy vs. retain)之间处理键的不同方式导致不同的



我研究了NSMutableDictionaryNSCache的差异。

其中一个是NSMutableDictionary复制它的key,而NSCache只保留它作为一个强引用。

另外,我发现之所以从NSMutableDictionary复制密钥,是因为如果只保留密钥,在更改密钥值后设置另一个值时会出现奇怪的情况。

let mutableDic = NSMutableDictionary()
var dicKey: NSString = "key"
mutableDic.setObject("one", forKey: dicKey)
dicKey = "changedKey"
mutableDic.setObject("two", forKey: dicKey)
print(mutableDic.object(forKey: "key") ?? "") //"one"
print(mutableDic.object(forKey: "changedKey") ?? "") //"two"

但是当我使用NSCache执行相同的操作时,我感到有些奇怪。因为它工作得很好,即使它不复制它的密钥!

let cache = NSCache<NSString, NSString>()
var cacheKey: NSString = "key"
cache.setObject("one", forKey: cacheKey)
cacheKey = "changedKey"
cache.setObject("two", forKey: cacheKey)
print(cache.object(forKey: "key") ?? "") //"one"
print(cache.object(forKey: "changedKey") ?? "") //"two"

所以我想知道,毕竟复制和保留会有什么不同的结果。

除了不需要将NScopying协议作为密钥实现外,保留密钥而不是复制密钥有什么好处吗?反之亦然?

你能举例说明吗?

这里的关键(ha)是在分配给dicKey/cacheKey。具体来说,赋值

dicKey = "changedKey"
cacheKey = "changedKey"

不改变原始dicKeycacheKey实例的值,而是创建新的字符串对象并设置局部变量指向这些新对象。


在字典的情况下:

  1. dicKey指向值为"key"的对象K₁
  2. mutableDic.setObject("one", forKey: dicKey)dicKey复制到一个新的key对象K₂中;K₁单独保留
  3. dicKey = "changedKey"创建一个值为"changedkey"的新对象K₃,并指定dicKey指向它
    • 由于不再指向K₁,其引用计数变为0,对象被释放
  4. mutableDic.setObject("two", forKey: dicKey)复制dicKey到一个新的key对象K₄;K₂被单独保留

最终结果是字典包含K₂和K₄,而dicKey指向K₃。


在缓存的情况下:

  1. dicKey指向值为"key"的对象K₁
  2. cache.setObject("one", forKey: cacheKey)保留K₁以插入缓存
  3. cacheKey = "changedKey"创建一个新对象K₂,其值为"changedKey"并赋值cacheKey指向它
    • 由于缓存仍然保留K₁,因此即使dicKey不再指向它,它仍保持活动并在内存中
  4. cache.setObject("two", forKey: cacheKey)保留K₂用于插入缓存

最终结果是缓存包含K₁和K₂,cacheKey指向K₂。


如果dicKeycacheKey不是NSString,而是NSMutableString,其值可以在运行时修改而无需创建新对象,那么在缓存情况下您将看到不同的行为:

let mutableDic = NSMutableDictionary()
var dicKey: NSMutableString = "key" // K₁
mutableDic.setObject("one", forKey: dicKey) // K₂
dicKey.setString("changedKey") // still K₁
mutableDic.setObject("two", forKey: dicKey) // K₃
print(mutableDic.object(forKey: "key") ?? "") // "one"
print(mutableDic.object(forKey: "changedKey") ?? "") // "two"
// BUT:
let cache = NSCache<NSString, NSString>()
var cacheKey: NSMutableString = "key" // K₁
cache.setObject("one", forKey: cacheKey) // still K₁
cacheKey.setString("changedKey") // still K₁
cache.setObject("two", forKey: cacheKey) // still K₁!
print(cache.object(forKey: "key") ?? "") // "" !!!
print(cache.object(forKey: "changedKey") ?? "") // "two"

相关内容

  • 没有找到相关文章

最新更新