编码复杂对象swift 3.0

时间:2017-05-25 05:37:42

标签: ios arrays swift nscoding nsarchiving

我已经阅读了几篇帖子并尝试了所有解决方案,但在我的案例中没有任何作用。

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

[_ 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 个答案:

答案 0 :(得分:3)

您不能开箱即用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()中的init(coder来电。

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

  • 归档像{{​​1}}这样的UI元素并不是一个好主意。存档图像数据。