2016-05-17 8 views
0

私は最初のSwift iOSアプリケーションで作業しています。サーバから取得したオブジェクトをシリアル化して保存するのに問題があります。私はGlossを使用しています。これは、JSONからインスタンスをインスタンス化できるDecodableプロトコルを定義する軽量JSON解析ライブラリです。私の意図はJSON[String : AnyObject]のタイプエイリアス)からそのIDを最初に抽出して、それからローカルアーカイブされたコピーを持っているかどうかをチェックすることによってものをロードすることです。もしそうすれば、これを解凍して画像を入手してください。そうでない場合は、イメージファイルの非同期要求を行います。NSCoderに準拠したクラスのインスタンスをアーカイブしようとしています

Thing.localArchiveExists(id)は常にfalseを返します。物は正しくインスタンス化されますが、常にイメージを再取得します。私はファイルシステムをチェックし、アーカイブファイルが書き込まれていないことを確認しました。しかし、「ERROR。Could not archive」と表示されていません。これは、保存が成功したことを私に示唆しています。 NSCoderオブジェクトをアーカイブして保存する方法について何か不足していますか?ありがとう!ここで

は、復号可能なプロトコルの私の実装です:ここでは

// MARK: Decodable protocol 
// When a thing is loaded from JSON, we load its image from archive if possible. 
required init?(json: JSON) { 
    guard let id: Int = "id" <~~ json else { return nil} 

    if Thing.localArchiveExists(id) { 
     guard let savedThing = NSKeyedUnarchiver.unarchiveObjectWithFile(Thing.archiveFilePath(id)) as? Thing else { return nil } 
     self.id = savedThing.id 
     self.name = savedThing.name 
     self.image = savedThing.image 
     self.imageUrl = savedThing.imageUrl 
     super.init() 
     print("Loaded Thing \(self.name) from archive") 
    } 
    else { 
     guard let name: String = "name" <~~ json else { return nil} 
     guard let imageUrl: NSURL = "url" <~~ json else { return nil} 
     self.id = id 
     self.name = name 
     self.imageUrl = imageUrl 
     super.init() 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
      let data = NSData(contentsOfURL: imageUrl) 
      dispatch_async(dispatch_get_main_queue(), { 
       self.image = UIImage(data: data!) 
       guard self.save() else { 
        print("ERROR. Could not archive") 
        return 
       } 
       print("Loaded Thing \(self.name) from server") 
      }) 
     } 
    } 
} 

はシングクラスの関連する部分です:

// MARK: Properties 
var id: Int? 
var name: String 
var imageUrl: NSURL? 
var image: UIImage? 

// MARK: Archiving Paths 
static let DocumentsDirectory = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! 
static let ArchiveURL = DocumentsDirectory.URLByAppendingPathComponent("things") 

// MARK: Types 
struct PropertyKey { 
    static let nameKey = "name" 
    static let imageKey = "image" 
    static let imageUrlKey = "imageUrl" 
    static let idKey = "id" 
} 

// Returns the file URL at which a Thing with the given ID should be saved. 
class func archiveFilePath(id: Int) -> String { 
    return Thing.ArchiveURL.URLByAppendingPathComponent("thing\(id)").absoluteString 
} 

// Checks whether an archived copy of a Thing with the given ID exists. 
class func localArchiveExists(id: Int) -> Bool { 
    let fileManager = NSFileManager.defaultManager() 
    return fileManager.fileExistsAtPath(Thing.archiveFilePath(id)) 
} 

// MARK: NSCoding 
func encodeWithCoder(coder: NSCoder) { 
    coder.encodeObject(name, forKey: PropertyKey.nameKey) 
    if image != nil { 
     coder.encodeObject(image!, forKey: PropertyKey.imageKey) 
    } 
    if imageUrl != nil { 
     coder.encodeObject(imageUrl!, forKey: PropertyKey.imageUrlKey) 
    } 
    coder.encodeInteger(id!, forKey: PropertyKey.idKey) 
} 

required convenience init?(coder aDecoder: NSCoder) { 
    let name = aDecoder.decodeObjectForKey(PropertyKey.nameKey) as! String 
    let image = aDecoder.decodeObjectForKey(PropertyKey.imageKey) as? UIImage 
    let imageUrl = aDecoder.decodeObjectForKey(PropertyKey.imageUrlKey) as? NSURL 
    let id = aDecoder.decodeIntegerForKey(PropertyKey.idKey) 

    // Must call designated initializer. 
    self.init(name: name, image: image, imageUrl: imageUrl, id: id) 
} 

func save() -> Bool {   
    // For some reason I can't archive to file. 
    return NSKeyedArchiver.archiveRootObject(self, toFile: Thing.archiveFilePath(self.id!)) 
} 
+1

...おそらく 'Thing'は' NSCoding'への準拠を宣言していますか? – Tommy

+0

問題はクラス内の構造体です。これはコーディングに準拠していません –

+0

@Tommy、はい、それは宣言されています: 'NSObject、NSCoding、Glossy {' – cproctor

答えて

0

私は私の問題を考え出した:私はまだ持っていたため、保存に失敗しました私は自分のものを保存しようとしていたディレクトリを作成しました。

func save() -> Bool {   
    let archivedData = NSKeyedArchiver.archivedDataWithRootObject(self) 
    do { 
     try NSFileManager.defaultManager().createDirectoryAtURL(Thing.ArchiveURL, withIntermediateDirectories: true, attributes: [:]) 
     try archivedData.writeToFile(Thing.archiveFilePath(self.id!), options: []) 
     return true 
    } catch { 
     print(error) 
     return false 
    } 
} 
関連する問題