斯威夫特3:保存数组到UserDefaults错误 - 对象的计数从钥匙

问题描述:

我的应用程序崩溃计数不同,出现错误:斯威夫特3:保存数组到UserDefaults错误 - 对象的计数从钥匙

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSDictionary initWithObjects:forKeys:]: count of objects (0) differs from count of keys (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字符串。
但我想知道现在的问题可能在哪里。

+0

你为什么使用'encodeCInt'?应该是'coder.encode(placeId !, forKey:“placeId”)' –

+0

顺便说一句,为什么你不声明你的AppAnnotation类属性为常量? –

+0

谢谢,我注意到整数编码。但为什么类的属性应该是常量? – Vad

强行拆包的问题。

NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Int: AppAnnotation] 

使用

NSKeyedUnarchiver.unarchiveObject(with: decoded) as? [Int: AppAnnotation] 

退房的方法定义:

open class func unarchiveObject(with data: Data) -> Any? 

它返回可选值。

+0

为什么要解决这个问题?它只会避免应用程序崩溃。 –

+0

更改为?没有帮助。同样的错误。这可能是我构造数组的方式:[Int:AppAnnotation]?如果我只重做[AppAnnotation]会怎么样? – Vad

+0

除此之外,其他一切看起来不错。您可以卸载应用程序并重新安装。以前的持久数据可能存在问题。 –