LoginSignup
4
4

More than 5 years have passed since last update.

Swiftでカスタムモデルオブジェクトをアーカイブファイルで永続化する(ドゥタンバヌマサカノ燕返し編)

Last updated at Posted at 2016-10-24

SwiftReverse

概要

  • RealmSwift を用いて特定のデータの永続化を行なうことになった
    • RealmSwift 箇所でアーカイブビルド時にエラーが発生(シミュレータやXCodeから直接実機に入れた際には問題なし、配布形式ビルドだとダメ)
      • おそらく RealmSwift 0.120.1 に混在する不具合らしきことが分かった
      • XCodeのバージョンを上げる必要があったため、やむを得ずRealmSwiftを断念
  • 代わりに CoreData を導入しようとしたが、マイグレーションや導入コストがかかり期間的に厳しい
    • Documentファイルで永続化
      • どの言語でもファイル操作は意外と基本的な事ぽいが調べてもなかなか情報が出てこなかった
      • NSUserDefaults に保存するパターンや単純な文字列をテキスト保存するなどはたくさん紹介されている

やりたい事

  • ある登録フォームの特定情報を一定期間保持したい
    • NSUserDefaults での保存ではなく単純なファイルとして保存したい

アプローチ

  • 永続化対象データをシリアライズしてバイナリ化しDocumentファイルとして保持
    • NSKeyedArchiver でシリアライズ保存、 NSKeyedUnarchiver で取り出す

設計

実装

  • キーポイントは NSObject クラスは NSCoding を継承しなければアーカイブ化できない
  • ※今回は ViewController は割愛

model

import Foundation

//MARK: - FormModel
public class FormModel: NSObject, NSCoding {
    public var id: String
    public var registerDatetime: NSDate
    public var name: String

    public override init() {
        self.id = NSUUID().UUIDString
        self.registerDatetime = NSDate()
        self.name = ""
    }

    required public init?(coder aDecoder: NSCoder) {
        self.id = aDecoder.decodeObjectForKey("id") as! String
        self.registerDatetime = aDecoder.decodeObjectForKey("registerDatetime") as! NSDate
        self.name = aDecoder.decodeObjectForKey("name") as! String
    }

    public func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.id, forKey: "id")
        aCoder.encodeObject(self.registerDatetime, forKey: "registerDatetime")
        aCoder.encodeObject(self.name, forKey: "name")
    }
}

manager

import Model

class CacheManager {
    static let instance = CacheManager()
    private let path: String
    private let fileName: String

    init() {
        self.path = NSHomeDirectory() + "/Documents/"
        self.fileName = "FormCache.cache"
    }

    internal func add(form: FormParam) -> Void {
        let cache = FormModel()
        cache.id = form.id != nil ? form.id! : 0
        cache.registerDatetime = form.registerDatetime
        cache.name = form.name

        NSKeyedArchiver.archiveRootObject(cache, toFile: self.path + self.fileName)
    }


    private func get() -> [FormModel] {        
        return NSKeyedUnarchiver.unarchiveObjectWithFile(self.path + self.fileName) as! [FormModel]
    }
}

まとめ

  • 単純な少量データには適しているが、本来ならば横着せずにCoreDataやSQLiteなどを用いて管理した方がいい
    • もちろんファイルで管理するメリットもたくさんあるのでケースバイケース
  • しっかし、iOSアプリ開発はなにかとトラップが多い気がする。XCodeにしろ、細かい制約にしろ、いろいろと難しい
4
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4