2017-01-04 52 views
0

Я соответствовал следующему классу Person протоколу NSCoding.Соответствующий класс для NSCoding

class Person: NSObject, NSCoding{ 

    var age:Int 
    var height: Double 
    var name: String 

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

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

    required init?(coder aDecoder: NSCoder){ 
     age = aDecoder.decodeObject(forKey: "age") as! Int **//error** 
     height = aDecoder.decodeObject(forKey: "height") as! Double 
     name = aDecoder.decodeObject(forKey: "name") as! String 
     super.init() 
    } 


} 

Затем я создал массив этого класса. Я архивировал его на plist, используя NSKeyedArchiver, и все было хорошо. Однако, когда я попытался разблокировать его, у меня возникла ошибка, связанная с распаковкой дополнительного, который был нулем. Ошибка появилась в классе Person, где отмечено. Это код, который я использовал:

if let people = unarchive(){ 
      print(people) 
} 

Вот функция для разархивирования:

func unarchive()->[Person]?{ 
    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) 
    let documentDirectory = paths[0] 
    let path = documentDirectory.appending("ObjectData.plist") 
    let fileManager = FileManager.default 
    if(!fileManager.fileExists(atPath: path)){ 
     if let bundlePath = Bundle.main.path(forResource: "ObjectData", ofType: "plist"){ 
      do{ 
       try fileManager.copyItem(atPath: bundlePath, toPath: path) 
      }catch{ 
       print("problem copying") 
      } 
     } 
    } 
    if let objects = NSKeyedUnarchiver.unarchiveObject(withFile: path){ 
     if let people = objects as? [Person]{ 
      return people 
     }else{ 
      return nil 
     } 
    }else{ 
     return nil 
    } 
} 

ответ

0

Int и Double не архивируются в качестве объектов. aDecoder.decodeObject(forKey: <key>) для них всегда будет возвращаться nil, и с помощью as! с nil будет разбиваться ваше приложение.

Таким образом, вместо того, чтобы использовать эту функцию:

aDecoder.decodeInteger(forKey: "age") 
aDecoder.decodeDouble(forKey: "height") 

Для name поле вы можете сохранить ваш код.

-1

Вы должны использовать надлежащие методы декодирования для Int и Double. Вы можете вставить следующий код на площадку и проверить его:

import Foundation 

class Person: NSObject, NSCoding{ 

    var age:Int 
    var height: Double 
    var name: String 

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

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

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

let john = Person(age: 30, height: 170, name: "John") 
let mary = Person(age: 25, height: 140, name: "Mary") 

let guys = [john, mary] 

let data = NSKeyedArchiver.archivedData(withRootObject: guys) 
let people = NSKeyedUnarchiver.unarchiveObject(with: data) 

dump (people)