【问题标题】:How to save an array of classes in swift code如何在快速代码中保存一组类
【发布时间】:2017-07-10 13:03:32
【问题描述】:

我正在尝试保存一个类数组,这是我目前的代码:

数组:

var person1 = person(name: "Bob", age: 22)
var person2 = person(name: "John", age: 10)
var array = [person1, person2]

自定义类:

import UIKit

class person: NSObject, NSCoding {

    var name : String
    var age : Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    required init (coder aDecoder: NSCoder) {
        name = (aDecoder.decodeObject(forKey: "name") as? String)!
        age = (aDecoder.decodeObject(forKey: "age") as? Int)!
    }

   func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: "name")
        aCoder.encode(age, forKey: "age")
    }
}

保存数组:

let SavedData = NSKeyedArchiver.archivedData(withRootObject: array)

let defaults = UserDefaults.standard

defaults.set(SavedData, forKey: "myPeople")

加载数组:

let saveddata = UserDefaults.standard.object(forKey: "myPeople") as? Data

if saveddata != nil{
    array = (NSKeyedUnarchiver.unarchiveObject(with: saveddata!) as? [person])!
}

错误在age = (aDecoder.decodeObject(forKey: "age") as? Int)!这一行

Interface Builder 文件中的未知类 iewripple。

【问题讨论】:

    标签: arrays swift class


    【解决方案1】:

    发生错误是因为您正在编码 Int 但解码 object 失败。

    有一个专门的方法decodeInteger(forKey。

    请遵守类名以大写字母开头,变量名以小写字母开头的命名约定。

    class Person: NSObject, NSCoding {
    

    为解决问题,将init(coder方法改为

    required init(coder aDecoder: NSCoder) {
        name = aDecoder.decodeObject(forKey: "name") as! String
        age = aDecoder.decodeInteger(forKey: "age")
    }
    

    强制解包字符串是 100% 安全的,因为该值始终被编码为非可选。


    保存数组

    let savedData = NSKeyedArchiver.archivedData(withRootObject: array)
    UserDefaults.standard.set(savedData, forKey: "myPeople")
    

    加载数组

    if let savedData = UserDefaults.standard.object(forKey: "myPeople") as? Data {
        array = NSKeyedUnarchiver.unarchiveObject(with: savedData) as! [Person]
    }
    

    如果可选绑定 as? Data 成功,在这种情况下强制解包也是安全的。

    【讨论】:

      【解决方案2】:

      您不应该强制展开。尝试获取

      required init (coder aDecoder: NSCoder) {
          name = (aDecoder.decodeObject(forKey: "name") as? String)!
          age = (aDecoder.decodeObject(forKey: "age") as? Int)!
      }
      

      替换为

      required init (coder aDecoder: NSCoder) {
          name = aDecoder.decodeObject(forKey: "name") as? String ?? ""
          age = aDecoder.decodeInteger(forKey: "age")
      }
      

      获取

      let saveddata = UserDefaults.standard.object(forKey: "myPeople") as? Data
      if saveddata != nil{
          array = (NSKeyedUnarchiver.unarchiveObject(with: saveddata!) as? [person])!
      }
      

      替换为

      if let data = UserDefaults.standard.object(forKey: "myPeople"),
          let array = NSKeyedUnarchiver.unarchiveObject(with: data as! Data) as? [person] {
          persons = array
      }
      

      我已经测试过了。代码工作正常。

      let person1 = person(name: "Bob", age: 22)
      let person2 = person(name: "John", age: 10)
      var persons = [person1, person2]
      
      // Save data
      let data = NSKeyedArchiver.archivedData(withRootObject: persons)
      let defaults = UserDefaults.standard
      defaults.set(data, forKey: "myPeople")
      
      // Load data
      if let data = UserDefaults.standard.object(forKey: "myPeople"),
          let array = NSKeyedUnarchiver.unarchiveObject(with: data as! Data) as? [person] {
          persons = array
      }
      

      此外,习惯上将类名的第一个字母大写。您可以查看this 以了解命名约定。

      【讨论】:

      • 感谢您的回答,但是 xcode 不允许我不强制展开。它告诉我添加为!年龄后的诠释
      • 我的应用程序现在没有崩溃,而是将每个人的姓名和年龄设置为“”和 0
      • 在这种情况下,强制展开非常好。该类始终对两个非可选属性进行编码,因此解码数据永远不会是nil。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      • 2015-11-24
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多