编码复杂对象swift 3.0

Posted

技术标签:

【中文标题】编码复杂对象swift 3.0【英文标题】:Encode complex object swift 3.0 【发布时间】:2017-05-25 05:37:42 【问题描述】:

我已经阅读了几篇文章并尝试了所有解决方案,但在我的情况下没有任何效果。

我正在使用这种复杂的数据结构,需要将 DrawnObjects 数组存储在文件中。但是当它第一次对一个本身是一个结构类型数组的变量进行编码时,它就崩溃了。有什么帮助吗?

[_SwiftValue encodeWithCoder:]:无法识别的选择器发送到实例 0x1702668c0

enum ArchiverKeys : String

    case imageView = "ImageView"
    case stateArray = "StateArray"
    case bezierPathArray = "BezierPathArray"
    case reactangleArray = "ReactangleArray"
    case deleted = "Deleted"

   struct RectanglePath 
        var point1: CGPoint
        var point2: CGPoint
        var point3: CGPoint
        var point4: CGPoint
    

    struct StateObject 
        var isAdd = true
        var path  = String()
    

    class DrawObject: NSObject , NSCoding 

        var ImageView = UIImageView()
        var arrStates = [StateObject]()
        var arrBezierPaths = [UIBezierPath]()
        var rects = [RectanglePath]()
        var deleted = false


        override init() 
            ImageView = UIImageView()
            arrStates = []
            arrBezierPaths = []
            rects = []
            deleted = false
        

        func encode(with archiver: NSCoder) 
            archiver.encode(self.ImageView, forKey:ArchiverKeys.imageView.rawValue )
            archiver.encode(self.arrStates, forKey: ArchiverKeys.stateArray.rawValue)
            archiver.encode(self.arrBezierPaths, forKey:ArchiverKeys.bezierPathArray.rawValue )
            archiver.encode(self.rects, forKey: ArchiverKeys.reactangleArray.rawValue)
            archiver.encode(self.deleted, forKey: ArchiverKeys.deleted.rawValue)
        

        required convenience init(coder unarchiver: NSCoder) 

            self.init()

            self.ImageView      = unarchiver.decodeObject(forKey: ArchiverKeys.imageView.rawValue) as! UIImageView
            self.arrStates      = unarchiver.decodeObject(forKey: ArchiverKeys.stateArray.rawValue) as! [StateObject]
            self.arrBezierPaths = unarchiver.decodeObject(forKey: ArchiverKeys.bezierPathArray.rawValue) as! [UIBezierPath]
            self.rects          = unarchiver.decodeObject(forKey: ArchiverKeys.reactangleArray.rawValue) as! [RectanglePath]
            self.deleted        = (unarchiver.decodeObject(forKey: ArchiverKeys.deleted.rawValue) != nil)
        
    

    func saveArrayTo(_ directoryName: String , arrayToSave: NSArray) 

     //   let encodedData = NSKeyedArchiver.archivedData(withRootObject: arrayToSave)
      NSKeyedArchiver.archiveRootObject(arrayToSave, toFile: directoryName)
    

     func loadArrayFrom(_ directoryName: String ) -> NSArray? 
        let result = NSKeyedUnarchiver.unarchiveObject(withFile: directoryName)
        return result as? NSArray
    

【问题讨论】:

【参考方案1】:

你不能开箱即用地编码一个 Swift 结构,你必须添加一个计算属性和一个 init 方法来使结构属性列表兼容

struct StateObject 
    var isAdd = true
    var path  = ""

    init(propertyList : [String:Any]) 
        self.isAdd = propertyList["isAdd"] as! Bool
        self.path = propertyList["path"] as! String
    

    var propertyListRepresentation : [String:Any] 
        return ["isAdd" : isAdd, "path"  : path]
    

现在您可以归档数组了

archiver.encode(self.arrStates.map$0.propertyListRepresentation, forKey: ArchiverKeys.stateArray.rawValue)

并取消归档

let states = unarchiver.decodeObject(forKey: ArchiverKeys.stateArray.rawValue) as! [[String:Any]]
self.arrStates = states.map  StateObject(propertyList: $0) 

或者将StateObject保持不变并

encode(with 替换行

archiver.encode(self.arrStates, forKey: ArchiverKeys.stateArray.rawValue)

let arrStatesAsPlist = arrStates.map  return ["isAdd" : $0.isAdd, "path" : $0.path] 
archiver.encode(arrStatesAsPlist, forKey:ArchiverKeys.stateArray.rawValue)

init(coder 替换行

archiver.encode(self.arrStates, forKey: ArchiverKeys.stateArray.rawValue)

let arrStatesAsPlist = unarchiver.decodeObject(forKey: ArchiverKeys.stateArray.rawValue) as! [[String:Any]]
arrStates = arrStatesAsPlist.map  StateObject(isAdd: $0["isAdd"] as! Bool, path: $0["path"] as! String) 

注意事项:

由于您正在为所有属性分配默认值,因此您可以删除整个 init() 方法和 init(coder 中的 init() 调用。

不要在 Swift 中使用 NSArray。使用原生Array

归档像 UIImageView 这样的 UI 元素不是一个好主意。存档图像数据。

【讨论】:

天啊,它奏效了。非常感谢@vadian。现在我正在努力保存图像而不是图像视图。

以上是关于编码复杂对象swift 3.0的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Swift 3.0 解析这个 JSON 对象

使用 Alamofire 3.0+ 在 swift 2.2 中使用 JSON 对象发送 POST 请求

在 Swift 3.0 中访问从 iTunes API 解析的 JSON 对象

在 Swift 3.0 中,没有在数组中的索引处获取对象的键值语法

在 Swift 中编码对象

Swift 2.0 + Alamofire 3.0 - 缓慢加载 JSON