无法更新NSMutableDictionary?

时间:2016-02-03 20:44:32

标签: swift nsmutabledictionary

我不明白为什么我在这个方法上出错:

let loginCountKey = "loginCount"
let appReviewParamsKey = "appReviewParams"

func resetLoginCount() {
    let defaults = NSUserDefaults.standardUserDefaults()

    if let reviewParameters = defaults.valueForKey(appReviewParamsKey) as? NSMutableDictionary {
        reviewParameters[loginCountKey] = 1

        defaults.setObject(reviewParameters, forKey: appReviewParamsKey)
        defaults.synchronize()
    }
}

setObject行给出了一个错误:caught "NSInternalInconsistencyException", ... mutating method sent to immutable object"

调试时,reviewParameters显示为NSMutableDictionary。我也试过if var而不是if let(因为它应该是不必要的)并且得到了同样的错误。

我也尝试将值设置为NSNumber(int:1)而不是1。

为什么会导致给定错误?

2 个答案:

答案 0 :(得分:1)

有两个问题:

  • NSUserDefaults在转换为基础类型
  • 时返回不可变对象
  • 即使返回的值是可变的,你也将它赋给了一个常量(let),这使得该对象在Swift中不可变。

在Swift中,推荐的方法是使用本机Swift类型和变量(var),例如

func resetLoginCount() {
  let defaults = NSUserDefaults.standardUserDefaults()

  if var reviewParameters = defaults.objectForKey(appReviewParamsKey) as? [String:AnyObject] {
    reviewParameters[loginCountKey] = 1

    defaults.setObject(reviewParameters, forKey: appReviewParamsKey)
    defaults.synchronize()
  }
}

答案 1 :(得分:1)

NSUserDefaults.objectForKey(一般KVC方法valueForKey必须调用的地方)在找到该默认密钥的字典格式数据时返回不可变NSDictionary

使用as?强制转换,而不是转换。也就是说,你告诉Swift解释你拥有的词典好像它是 NSMutableDictionary(即使它没有,这就是失败的原因)。如果您想转换 NSDictionaryNSMutableDictionary,您需要从前者创建后者的实例(使用mutableCopyinitWithDictionary:)。

但是你甚至不需要在这里使用Foundation词典 - NSDictionary会自动桥接到Swift词典,你可以强制转换为as正确的键/值类型。您可以使用if var代替if let将可选项绑定为可变值:

if var reviewParameters = defaults.objectForKey(appReviewParamsKey) as? [String: Int] {
    reviewParameters[loginCountKey] = 1

    defaults.setObject(reviewParameters, forKey: appReviewParamsKey)
    defaults.synchronize()
}