I studied the differences between NSMutableDictionary and NSCache.
One of them was that NSMutableDictionary copy its keys and NSCache just retain it as a strong reference.
In addition, I found that the reason why the key is copied from the NSMutableDictionary is that if the key is only retained, a strange situation occurs when setting another value after changing the key value.
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"
But when I performed the same action using NSCache I felt something strange. Because it worked fine even though it does not copy its keys!
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"
So I wonder, after all what the different results will be from copying and retaining.
Is there any advantage to retain keys rather than copy except no need to implement the NScopying protocol as a key? or vice versa?
Can you explain with examples?
The key here (ha) is in the assignment to
dicKey/cacheKey. Specifically, the assignmentsare not changing the value of the original
dicKeyandcacheKeyinstances, but creating new string objects and setting the local variables to point to these new objects.In the dictionary case:
dicKeypoints to an object K₁ whose value is "key"mutableDic.setObject("one", forKey: dicKey)copiesdicKeyinto a new key object K₂; K₁ is left alonedicKey = "changedKey"creates a new object K₃ with the value "changedKey", and assignsdicKeyto point to itmutableDic.setObject("two", forKey: dicKey)copiesdicKeyinto a new key object K₄; K₂ is left aloneThe end result is that the dictionary contains K₂ and K₄, while
dicKeypoints to K₃.In the cache case:
dicKeypoints to an object K₁ whose value is "key"cache.setObject("one", forKey: cacheKey)retains K₁ for insertion into the cachecacheKey = "changedKey"creates a new object K₂ with a value "changedKey" and assignscacheKeyto point to itdicKeyno longer points to itcache.setObject("two", forKey: cacheKey)retains K₂ for insertion into the cacheThe end result is that the cache contains K₁ and K₂, and
cacheKeypoints to K₂.If instead of being an
NSString,dicKeyandcacheKeywereNSMutableString, whose value can be modified at runtime without creating a new object, you'd see different behavior in the cache case: