2016-05-17 34 views
0

我正在處理我的第一個Swift iOS應用程序,它無法序列化並保存從服務器獲取JSON的對象。我正在使用Gloss,這是一個輕量級的JSON解析庫,它定義了一個Decodable協議,通過它可以從JSON實例化一個實例。我的意圖是從JSON[String : AnyObject]的一個類型別名)加載一個東西,首先提取它的ID,然後檢查我是否已經有一個本地存檔副本。如果我這樣做,解開這個並獲得圖像。如果沒有,請爲圖像文件進行異步請求。試圖歸檔符合NSCoder的類的一個實例

問題是Thing.localArchiveExists(id)總是返回false。事物已成功實例化,但它們總是重新獲取圖像。我檢查了文件系統並確認沒有正在寫入的檔案文件。但是,我沒有看到「錯誤。無法存檔」,這表明保存成功。我錯過了如何存檔和保存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") 
      }) 
     } 
    } 
} 

這裏是Thing類的相關部分:

// 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,是的,Thing被聲明爲:'類Thing: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 
    } 
} 
相關問題