Swift 可变字典被视为不可变

标签 swift nsuserdefaults immutability nsmutabledictionary

我正在尝试实现 In App Purchases,我正在跟踪用户通过 NSUserDefaults 购买了哪些商品。我有一个函数可以设置每次购买的值(value),但是当它运行时,我收到一条错误消息,指出我正在改变购买值(value)的字典,即使该字典是用 var 而不是let 并且是一个 NSMutableDictionary。有时它确实有效,但大多数时候无效。我收到一些关于使用 let 而不是 var 声明我的变量的警告,但我忽略它们以使我的变量具有最大的可变性。为什么这不起作用?

我得到的错误是:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'

代码:

static func setPurchased(purchase:PurchaseID, value:Bool)
{
    let defaults = NSUserDefaults.standardUserDefaults()

    if (defaults.objectForKey(PURCHASES_KEY) == nil)
    {
        initializePurchases()       // go set some initial values
    }

    if var purchases = (defaults.objectForKey(PURCHASES_KEY) as? NSMutableDictionary)   // WARNING: should be declared with let because not mutated
    {
        print("setting purchase \(purchase.id()) to \(value)")
        var key = purchase.id()   // WARNING: should be declared with let because not mutated

        purchases[key] = value    // CRASH HERE
        defaults.setObject(purchases, forKey:PURCHASES_KEY)
        defaults.synchronize()
    }
}

最佳答案

这不是将不可变字典转换为可变字典的正确方法。

var已经确保从 defaults.objectForKey(PURCHASES_KEY) 返回的任何内容将被复制为可变类型,因此您只需指定可变对象的类型,在我们的例子中可以安全地为 Dictionary<String: AnyObject>如果您确定所有键都是 String输入:

if var purchases = defaults.objectForKey(PURCHASES_KEY) as? Dictionary<String: AnyObject> {
  ...
  purchases[key] = value
}

请参阅this SO question有关集合类型的可变性/不变性的更多信息。

关于Swift 可变字典被视为不可变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37220458/

相关文章:

如果我们只允许局部变量是可变的,我们可以防止共享可变状态吗?

swift - Firestore 查询选项 swift

ios - 将 AVAudioPCMBuffer 转换为 NSData

ios - 重复图像下载过程

ios - BOOL 未保存在用户默认值中

javascript - Redux 'connect' 未检测到状态数组更改

swift - 核心数据性能问题

ios - 保存和加载自定义字典 ​​- NSUserDefaults

ios - 在 Swift 中将 NSUserDefaults 与 suiteName 一起使用

c# - 只读是否有任何运行时开销?