NSMutableDictionary 和 NSCache 之间处理键的不同方式(复制与保留)是否会导致不同的结果?
Does the different way of handling key between NSMutableDictionary and NSCache (copy vs. retain) result in different consequence?
我研究了NSMutableDictionary
和NSCache
的区别。
其中之一是 NSMutableDictionary
复制它的密钥,NSCache
只是保留它作为一个强有力的参考。
另外我发现之所以从NSMutableDictionary
复制key是因为如果只保留key的话,改变key值后设置另一个值会出现奇怪的情况
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"
不会更改 原始 dicKey
和 cacheKey
实例的值,而是创建新的字符串对象并将局部变量设置为指向这些实例新对象。
字典大小写:
dicKey
指向一个值为“key”的对象K₁
mutableDic.setObject("one", forKey: dicKey)
将 dicKey
复制到新的密钥对象 K2 中; K₁ 独自留下
dicKey = "changedKey"
创建一个新的对象 K₃,值为“changedKey”,并赋值 dicKey
指向它
- 因为没有任何东西再指向 K₁,它的引用计数变为 0,对象被释放
mutableDic.setObject("two", forKey: dicKey)
将 dicKey
复制到新的密钥对象 K₄ 中; K₂ 被单独留下
最终结果是字典中包含K2和K4,而dicKey
指向K3。
缓存情况下:
dicKey
指向一个值为“key”的对象K₁
cache.setObject("one", forKey: cacheKey)
保留 K₁ 用于插入缓存
cacheKey = "changedKey"
创建一个新对象 K2,其值为“changedKey”,并赋值 cacheKey
指向它
- 由于缓存仍然保留着 K₁,它仍然存在并在内存中,即使
dicKey
不再指向它
cache.setObject("two", forKey: cacheKey)
保留 K2 用于插入缓存
最终结果是缓存中有K₁和K₂,cacheKey
指向K₂。
如果不是 NSString
,dicKey
和 cacheKey
是 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"
我研究了NSMutableDictionary
和NSCache
的区别。
其中之一是 NSMutableDictionary
复制它的密钥,NSCache
只是保留它作为一个强有力的参考。
另外我发现之所以从NSMutableDictionary
复制key是因为如果只保留key的话,改变key值后设置另一个值会出现奇怪的情况
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"
不会更改 原始 dicKey
和 cacheKey
实例的值,而是创建新的字符串对象并将局部变量设置为指向这些实例新对象。
字典大小写:
dicKey
指向一个值为“key”的对象K₁mutableDic.setObject("one", forKey: dicKey)
将dicKey
复制到新的密钥对象 K2 中; K₁ 独自留下dicKey = "changedKey"
创建一个新的对象 K₃,值为“changedKey”,并赋值dicKey
指向它- 因为没有任何东西再指向 K₁,它的引用计数变为 0,对象被释放
mutableDic.setObject("two", forKey: dicKey)
将dicKey
复制到新的密钥对象 K₄ 中; K₂ 被单独留下
最终结果是字典中包含K2和K4,而dicKey
指向K3。
缓存情况下:
dicKey
指向一个值为“key”的对象K₁cache.setObject("one", forKey: cacheKey)
保留 K₁ 用于插入缓存cacheKey = "changedKey"
创建一个新对象 K2,其值为“changedKey”,并赋值cacheKey
指向它- 由于缓存仍然保留着 K₁,它仍然存在并在内存中,即使
dicKey
不再指向它
- 由于缓存仍然保留着 K₁,它仍然存在并在内存中,即使
cache.setObject("two", forKey: cacheKey)
保留 K2 用于插入缓存
最终结果是缓存中有K₁和K₂,cacheKey
指向K₂。
如果不是 NSString
,dicKey
和 cacheKey
是 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"