【问题标题】:setObject:forKey: mutating method sent to immutable objectsetObject:forKey: 发送到不可变对象的变异方法
【发布时间】:2016-06-03 21:53:24
【问题描述】:

我错过了什么...?

在我项目的其他地方有这样的代码:

let allUsers = ["userName":["difficulty": 1, "highscore": 50],"userName2":["difficulty": 2, "highscore: 75]]          
defaults.setObject(allUsers, forKey: "allUsers")

我想为该用户数组中的一个用户更改一个值:

var allUsers = defaults.objectForKey("allUsers") as! [String:NSMutableDictionary]

let changingUser = allUsers["userName"]! as NSMutableDictionary

这些都不行:

changingUser.setObject(3, forKey: "difficulty")
changingUser["difficulty"] = 3

出现错误:

*** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object”

【问题讨论】:

  • objectForKey 返回的对象将是不可变的。您不能简单地将不可变字典向下转换为可变字典。您需要从用户默认返回的数组中创建一个新的 NSMutableArray,对其进行修改,然后将其写回。
  • 您也可以最初键入您的 allUsers 字典,例如 let allUsers: [String:NSMutableDictionary] = ...。那时您对 NSMutableDictionary 的转换是正确的。

标签: ios swift nsmutabledictionary


【解决方案1】:

您不能只将NSDictionary 转换为NSMutableDictionary。您可以通过传入一个不可变的副本来初始化一个,但不幸的是,这不是一个深层的可变结构。

但是,您可以将其转换为 Swift Dictionary 并将其分配给 var:

var allUsers = defaults.objectForKey("allUsers") as? [String: [String: Int]] ?? [:]
allUsers2["userName"]?["difficulty"] = 3

但请注意,Swift 字典是值对象并且具有值语义。也就是说,如果您按以下步骤执行此操作:

var allUsers = defaults.objectForKey("allUsers") as? [String: [String: Int]] ?? [:]
changingUser = allUsers["userName"]
changingUser?["difficulty"] = 3 //mutates a copy

这行不通,因为changingUser 是一个副本,在写入它时,它会改变它,它不会改变allUsers 字典。因此,您必须将更改后的内部 dict 写回外部 dict,或者像我上面那样做。

【讨论】:

  • 所以它检查 allUsers 是否是一个 [String: [String: Int]] 如果不是那么 [:] 做什么?只是将它设置为 AnyObjects 数组?就我而言,它将始终是 [String: [String: Int]]。谢谢!
  • 不,类型系统保证给定变量(或常量)始终具有一致的类型。所以 ??部分是强制转换失败的默认值,它返回一个空字典,但仍然是 [String: [String: Int]] 类型
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
  • 2016-11-17
  • 1970-01-01
相关资源
最近更新 更多