私は最初の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!))
}
...おそらく 'Thing'は' NSCoding'への準拠を宣言していますか? – Tommy
問題はクラス内の構造体です。これはコーディングに準拠していません –
@Tommy、はい、それは宣言されています: 'NSObject、NSCoding、Glossy {' – cproctor