簡體   English   中英

嘗試存檔符合NSCoder的類的實例

[英]Trying to archive an instance of a class conforming to NSCoder

我正在開發我的第一個Swift iOS應用程序,無法序列化和保存從服務器獲取其JSON的對象。 我正在使用Gloss ,這是一個輕量級的JSON解析庫,該庫定義了Decodable協議,通過該協議可以從JSON實例化實例。 我的意圖是通過首先提取其ID從JSON[String : AnyObject]的類型別名)中加載事物,然后檢查是否已具有本地存檔副本。 如果這樣做,請取消存檔並獲取圖像。 如果不是,則對圖像文件發出異步請求。

問題在於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!))
}  

我發現了我的問題:保存失敗,因為我還沒有創建試圖保存Thing的目錄。

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
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM