2017-03-20 20 views
0

Swift 3でNSkeyedアーカイブとして保存されたオブジェクトを取得することはできません。オブジェクトが正常のplistとして保存されますが、後ろにロードするときにはnilとして返されSwift3で正しく保存されたNSKeyArchivedオブジェクトを取得できません。

ここで私が使用するコードです:。

クラス自体がオブジェクトとして保存することが非常に簡単です:

import Foundation 

class ItemList:NSObject, NSCoding { 

    var name: String = "" //Name of the Item list 
    var contents: [Int] = [] //Ints referencing the CoreData PackItems 

    init (listname:String, ContentItems:[Int]) { 
     self.name=listname 
     self.contents=ContentItems 
    } 

    //MARK: NSCoding 
    public convenience required init?(coder aDecoder: NSCoder) { 
     let thename = aDecoder.decodeObject(forKey: "name") as! String 
     let thecontents = aDecoder.decodeObject(forKey: "contents") as! [Int] 
     self.init(listname: thename,ContentItems: thecontents) 
    } 

    func encode(with aCoder: NSCoder) { 
     aCoder.encode(self.name,forKey:"name") 
     aCoder.encode(self.contents, forKey: "contents") 
    } 

} 

オブジェクトのロードおよび保存するためのコード:

class FileHandler: NSObject { 

    class func getDocumentsDirectory() -> URL { 
     let filemgr = FileManager.default 
     let urls = filemgr.urls(for: .documentDirectory, in: .userDomainMask) 
     let result:URL = urls.first! 
     return result 
    } 

    ///This returns the contents of the handed file inside the Documents directory as the object it was saved as. 
    class func getFileAsObject(filename:String) -> AnyObject? { 

     let path = getDocumentsDirectory().appendingPathComponent(filename) 

     if let result = NSKeyedUnarchiver.unarchiveObject(withFile: path.absoluteString) { 
      //Success 
      print("Loaded file '"+filename+"' from storage") 
      return result as AnyObject? 
     } else { 
      print("Error: Couldn't find requested object '"+filename+"' in storage at "+path.absoluteString) 
      return nil 
     } 
    } 

    ///This saves the handed object under the given filename in the App's Documents directory. 
    class func saveObjectAsFile(filename:String, Object:AnyObject) { 
     let data = NSKeyedArchiver.archivedData(withRootObject: Object) 
     let fullPath = getDocumentsDirectory().appendingPathComponent(filename) 

     do { 
      try data.write(to: fullPath) 
      print("Wrote file '"+filename+"' to storage at "+fullPath.absoluteString) 
     } catch { 
      print("Error: Couldn't write file '"+filename+"' to storage") 
     } 
    } 

} 

を...そして最後に、これは私がそれをすべてを呼び出すために何をすべきかです:

そう私は(とチェックした)ファイルが正しく作成されたこと - これは私自身の出力であることを

Wrote file 'Test.plist' to storage at file:///…/data/Containers/Data/Application/6747B038-B0F7-4B77-85A8-9EA02BC574FE/Documents/Test.plist 
Error: Couldn't find requested object 'Test.plist' in storage at file:///…/data/Containers/Data/Application/6747B038-B0F7-4B77-85A8-9EA02BC574FE/Documents/Test.plist 

注:

let testobject:ItemList = ItemList.init(listname: "testlist", ContentItems: [0,0,1,2]) 

     FileHandler.saveObjectAsFile(filename:"Test.plist",Object:testobject) 
     let tobi = FileHandler.getFileAsObject(filename:"Test.plist") as! ItemList 

ああ、私は出力としてこれを取得します。しかし、それは単に読み込まれません。誰かが私が間違っていることを教えてもらえますか?

答えて

2

問題は、パスをunarchiveObject(withFile:)に渡すことです。

変更:

if let result = NSKeyedUnarchiver.unarchiveObject(withFile: path.absoluteString) { 

へ:

if let result = NSKeyedUnarchiver.unarchiveObject(withFile: path.path) { 

サイドノートでは、あなたの書き込みと読み出しロジックに対称のAPIを使用する必要があります。データを書き込むときは、ルートオブジェクトをDataオブジェクトにアーカイブしてからDataオブジェクトをファイルに書き込みます。しかし、読み込み時には、ファイルパスを指定してオブジェクトツリーを直接解凍してください。

書き込みコードをarchiveRootObject(_:toFile:)に変更するか、読み取りコードを変更してファイルからDataをロードし、データをアーカイブ解除します。現在のコードは動作します(一度パスの問題を修正すると)、一貫性がありません。

+0

マディさん、ありがとう、これは優秀かつ簡潔な答えでした! – Averett

関連する問題