2017-03-02 90 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