34
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NSUserDefaultsの代わりにRealmを使ってみると良いかもしれない

Posted at

NSUserDefaultsの代わりにRealmを使ってみると良いかもしれない

iOSアプリ内に何らかの設定値を保存する場合、基本的にNSUserDefaultsに保存しているかと思います。

ただしNSUserDefaultsは、[String:AnyObject]でアクセスしなければならず、Swiftでは結構扱いにくいです(ラッパークラスをうまく設計できていれば問題は起きないのかもしれませんが)。

それから色々な場所から色々なkeyで値が保存されるため、気がついたらどこに何が入っているか分からないということにも起きがちちゃないのではないでしょうか。

いろいろ考えてみたのですが、Realmを使うと"アプリの構造"を扱いやすくなるのではないのか、と思いました。こちらの記事でも同様のことが述べられています。

ということでRealmSwift簡単なサンプルを書いてみました。

サンプルコード解説

シンプルにユーザーの状態(ゲスト状態かログイン状態か)と、起動した日時を記録しようと思います。

サンプルではユーザーの状態をenumで定義しています。

AppPreferences.swift
enum UserState: String {
    case Guest, Login
}

Realmではenumはプロパティとして扱えないので、enumrawValueStringにしてプロパティに代入します。
そしてObjectを継承してAppStateを定義します。

AppPreferences.swift
class AppState: Object {
    dynamic var state: String = UserState.Guest.rawValue
    dynamic var launchDateTime: NSDate = NSDate()
}

以下のようなSingletonのRealmのラッパークラスを作成します。

AppPreferences.swift
final class AppStateManager {
    
    static let sharedInstance = AppStateManager()
    private init() {}

    private var realm: Realm {
        guard let realm = try? Realm() else {
            fatalError()
        }
        return realm
    }
    
    func update(userState: UserState ,launchDateTime: NSDate) {
        
        let state = AppState()
        state.state = userState.rawValue
        state.launchDateTime = launchDateTime
        
        do {
            try self.realm.write({ [weak self] () -> Void in
                
                guard let stateManager = self else {
                    return
                }

                stateManager.realm.add(state)
                })
        } catch {
            print("could not write")
        }
    }
}

こんな感じでアプリ起動時にRealmへ保存を行います。

AppDelegate.swift
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        AppStateManager.sharedInstance.update(UserState.Guest, launchDateTime: NSDate())
        return true
    }

AppDelegateoptional func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Boolで呼び出すことを想定しています。

まとめ

UserDefaultsにRealmを使ってみることについて考えてみましたが、実際に使う際には結構リスクが高位のだろうなとも感じました。リスクを考慮した上で、許容できるのであれば、個人的には良い解決方法になるのではないかなと思います。

以下に個人的に感じたメリット、デメリットについてまとめてみました。

メリット

  • AppStateなどの状態をモデルとして定義することで、どんな情報が保存されているのかが構造化されて分かりやすい
  • NSUserDefaultsから取り出す際のキャストが不要
  • 条件を指定して保存したデータの絞り込みがしやすい

デメリット

  • Realmが1.0を迎えていない現段階ではリスクになりそう
  • 既存のアプリに途中から入れることは難しそう
  • マイグレーション怖い

補足

僕はあまりDB周りは得意ではないので、もっと色々なことがメリット、デメリット考えられるかと思うので、ご指摘いただけると嬉しいです。

34
36
7

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
34
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?