2017-03-02 30 views
0

我有使用NSCoding和NSObject归档的一些问题。这在Playground中完美无瑕。但在Xcode中似乎并不适用。有人可以帮我解决这个问题吗?Xcode项目不使用NSKeyedArchiver存档,但游乐场做

每次我打电话:

NSKeyedArchiver.archiveRootObject(person, toFile: "person") 

它的工作原理,并在游乐场返回true,但在项目返回false。我不使用模拟器。

我一直在寻找相同类型的问题,但我似乎无法找到任何与此相关的任何内容。

class Person: NSObject, NSCoding { 

private var _name: String = "name" 
private var _birthdate: Date = Date() 
private var _income: Int = -1 
private var _wealth: Int = -1 

var name: String { 
    get { return _name } 
    set (newName) { _name = newName } 
} 
var birthdate: Date { 
    get { return _birthdate } 
    set (newBirthdate) { _birthdate = newBirthdate } 
} 
var income: Int { 
    get { return _income } 
    set (newIncome) { _income = newIncome } 
} 
var wealth: Int { 
    get { return _wealth } 
    set (newWealth) { _wealth = newWealth } 
} 

override init(){} 

required convenience init(coder unarchiver: NSCoder) { 

    self.init() 

    if let name = unarchiver.decodeObject(forKey: "name") as? String { 
     self.name = name 
    } 
    if let birthdate = unarchiver.decodeObject(forKey: "birthdate") as? Date { 
     self.birthdate = birthdate 
    } 
    let income = unarchiver.decodeInteger(forKey: "income") 
    self.income = income 

    let wealth = unarchiver.decodeInteger(forKey: "wealth") 
    self.wealth = wealth 

} 

func encode(with archiver: NSCoder) { 

    archiver.encode(name, forKey: "name") 
    archiver.encode(birthdate, forKey: "birthdate") 
    archiver.encode(income, forKey: "income") 
    archiver.encode(wealth, forKey: "wealth") 
} 
} 

然后我创建一个人并归档它。

let person = Person() 
NSKeyedArchiver.archiveRootObject(person, toFile: "person") 
+0

它看起来像filePath的问题。在我的知识中,Playgrounds实际上使用Home目录,但一个项目会使用沙箱。如果您使用类似于'FileManager.default.urls(用于:.documentDirectory,在:.userDomainMask).first!.appendingPathComponent(“person”)'? – Prientus

+0

我不知道文件管理器做什么,但我用这样的: '让人=人() 令路径= FileManager.default.urls(为:.documentDirectory在:.userDomainMask)。第一.appendingPathComponent( “人”) 让personWasUploaded:布尔= NSKeyedArchiver.archiveRootObject(人,TOFILE: “\(路径)”) 打印(路径) 打印( “上传人:\(personWasUploaded)”) ' – Jer

+0

它创建一个这样的文件: 'file:/// var/mobile/Containers/Data/Application/4843FF38-BEFD-47F0-A1E2-DE4ADDA97F/Documents/person'。但是,在应用程序和文档之间,每次更改数字/字母 – Jer

回答

2

您需要在Person类中对init进行一个小的编辑。取出convenience关键字和替换self.init()super.init()

class Person: NSObject, NSCoding { 

    private var _name: String = "name" 
    private var _birthdate: Date = Date() 
    private var _income: Int = -1 
    private var _wealth: Int = -1 

    var name: String { 
     get { return _name } 
     set (newName) { _name = newName } 
    } 
    var birthdate: Date { 
     get { return _birthdate } 
     set (newBirthdate) { _birthdate = newBirthdate } 
    } 
    var income: Int { 
     get { return _income } 
     set (newIncome) { _income = newIncome } 
    } 
    var wealth: Int { 
     get { return _wealth } 
     set (newWealth) { _wealth = newWealth } 
    } 

    override init() {} 

    required init(coder unarchiver: NSCoder) { 

     super.init() 

     if let name = unarchiver.decodeObject(forKey: "name") as? String { 
      self.name = name 
     } 
     if let birthdate = unarchiver.decodeObject(forKey: "birthdate") as? Date { 
      self.birthdate = birthdate 
     } 
     let income = unarchiver.decodeInteger(forKey: "income") 
     self.income = income 

     let wealth = unarchiver.decodeInteger(forKey: "wealth") 
     self.wealth = wealth 

    } 

    func encode(with archiver: NSCoder) { 

     archiver.encode(name, forKey: "name") 
     archiver.encode(birthdate, forKey: "birthdate") 
     archiver.encode(income, forKey: "income") 
     archiver.encode(wealth, forKey: "wealth") 
    } 
} 

一旦你这样做,你可以调用,无论你想(我做到了,我viewDidLoad中只是用于测试和它的工作)给它这样的路径归档:

let person = Person() 
let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("person").path 
let personWasUploaded: Bool = NSKeyedArchiver.archiveRootObject(person, toFile:path) 
print(path) 
print("person uploaded: \(personWasUploaded)") 
+0

谢谢你的回答!我找到了一种没有FileManager的方法,只是不使用FileManager,也像你所建议的那样改变init()。我猜主要问题是我如何初始化。 – Jer