Swift 3:将数组保存到 UserDefaults 错误 - 对象数与键数不同
Posted
技术标签:
【中文标题】Swift 3:将数组保存到 UserDefaults 错误 - 对象数与键数不同【英文标题】:Swift 3: Saving Array to UserDefaults Error - Count of Objects Differs from Count of Keys 【发布时间】:2017-05-18 13:35:41 【问题描述】:我的应用程序因错误而崩溃:
由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“*** -[NSDictionary initWithObjects:forKeys:]:对象数 (0) 与键数 (1) 不同
这是我保存var favoriteAppAnnotations = [Int: AppAnnotation]()
的方法:
let userDefaults = UserDefaults.standard
let favoritesData: Data = NSKeyedArchiver.archivedData(withRootObject: self.favoriteAppAnnotations)
userDefaults.set(favoritesData, forKey: "FAVORITES")
userDefaults.synchronize()
这是我的加载方式:
self.favoriteAppAnnotations = [:]
let userDefaults = UserDefaults.standard
if let decoded = userDefaults.object(forKey: "FAVORITES") as? Data
let favoritesArray = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Int: AppAnnotation] // THIS IS WHERE THE CRASH IS
if favoritesArray.isEmpty == false
self.favoriteAppAnnotations = favoritesArray
AppAnnotation 符合 NSCoding
如下:
class AppAnnotation: ParentAppAnnotation, NSCoding // Note: ParentAppAnnotation is NSObject but doe snot conform to NSCoding
open var placeId: Int?
open var placeName: String?
open var placeDescription: String?
override init()
super.init()
init(placeId: Int, placeName: String, placeDescription: String)
self.placeId = placeId
self.placeName = placeName
self.placeDescription = placeDescription
required convenience init?(coder decoder: NSCoder)
guard let placeName = decoder.decodeObject(forKey: "placeName") as? String,
let placeDescription = decoder.decodeObject(forKey: "placeDescription") as? String
else return nil
self.init(placeId: decoder.decodeInteger(forKey: "placeId"),
placeName: placeName,
placeDescription: placeDescription)
func encode(with coder: NSCoder)
coder.encodeCInt(Int32(self.placeId!), forKey: "placeId")
coder.encode(self.placeName, forKey: "placeName")
coder.encode(self.placeDescription, forKey: "placeDescription")
我放弃了问题所在。考虑保存数组的替代方法...例如转换为JSON
字符串。
但我想了解当前的问题可能出在哪里。
【问题讨论】:
你为什么使用encodeCInt
?应该是coder.encode(placeId!, forKey: "placeId")
顺便说一句,为什么不将 AppAnnotation 类属性声明为常量?
谢谢,我注意到整数编码。但是为什么类的属性应该是常量呢?
如果你需要改变它,只需创建一个新对象
BTW UserDefaults 有一个方法叫data(forKey:)
【参考方案1】:
强制展开的问题。
NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Int: AppAnnotation]
使用
NSKeyedUnarchiver.unarchiveObject(with: decoded) as? [Int: AppAnnotation]
查看方法定义:
open class func unarchiveObject(with data: Data) -> Any?
它返回可选值。
【讨论】:
为什么可以解决问题?它只会避免应用程序崩溃。 更改为 ?没有帮助。同样的错误。这可能是我构造数组的方式:[Int:AppAnnotation]?如果我只重做 [AppAnnotation] 会怎样? 除此之外,其他一切看起来都不错。您可以卸载该应用程序并重新安装。以前的持久数据可能存在问题。以上是关于Swift 3:将数组保存到 UserDefaults 错误 - 对象数与键数不同的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 将字典数组保存到 NSUserDefaults
Swift:将一个对象数组和另一个对象数组保存到 NSUserDefaults 中