2017-05-25 5 views
0

Ich habe bereits mehrere Beiträge gelesen und versuchte jede Lösung, nichts funktioniert in meinem Fall.Codieren Sie komplexe Objekt swift 3.0

Ich verwende diese komplexe Datenstruktur und muss Array von DrawnObjects in Datei speichern. Aber es stürzte ab, als es zum ersten Mal kam, um eine Variable zu kodieren, die selbst ein Array des Strukturtyps ist. Irgendeine Hilfe ?

[_SwiftValue encodeWithCoder:]: Unbekannter Selektor an Instanz gesendet aus dem Kasten 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 
    } 

Antwort

3

Sie struct ein Swift nicht kodieren, können Sie die eine berechnete Eigenschaft und eine init Methode hinzufügen müssen machen struct Eigenschaftsliste konform

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] 
    } 
} 

Jetzt können Sie das Array archivieren

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

und dearchivieren es

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

verlassen Alternativ StateObject unverändert und

  • in encode(with ersetzen Sie die Zeile

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

    mit

    let arrStatesAsPlist = arrStates.map { return ["isAdd" : $0.isAdd, "path" : $0.path] } 
    archiver.encode(arrStatesAsPlist, forKey:ArchiverKeys.stateArray.rawValue) 
    
  • in init(coder die Zeile ersetzen

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

    mit

    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) } 
    

Anmerkungen:

  • Da Sie allen Eigenschaften Standardwerte zuweisen, können Sie die gesamte Methode init() und den init() Aufruf in init(coder löschen.

  • Verwenden Sie nicht NSArray in Swift. Verwenden Sie einen nativen Array

  • Es ist keine gute Idee, ein UI-Element wie UIImageView zu archivieren. Archivieren Sie die Bilddaten.

+0

danke @vadian ich werde das versuchen und Sie wissen lassen. – ChanWarde

+0

OMG, es hat funktioniert. Vielen Dank @vadian. Jetzt arbeite ich daran, Bilder anstelle von Bildansicht zu speichern. – ChanWarde