iOSでRealmを使ってみたぞい

  • 37
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Realmとは

Realm is a mobile database
Realm is a replacement for SQLite & Core Data.
It can save you thousands of lines of code & weeks of work,
and lets you craft amazing new user experiences.

Realm

Realm、最近めちゃくちゃホットなモバイルのデータベースですね
昨今のSwift2移行で既存のアプリを書き換えるに際して、これまで使ってたSQLite3のラッパが動かなくなり、思い切ってRealmに移行しようって感じで使ってみました

Install

時代はPodsじゃなくてCarthageですよね
しらんけど

$ cat Cartfile
github "realm/realm-cocoa"
$ carthage update

そんでもってこうして

スクリーンショット 2015-10-06 8.49.29.png

はい、完了!
So Coooool!!!

使うゾイ

掲示板を閲覧する機能があるので、BoardStorageってクラスを作って、永続化させる

ソースはこんな感じ

import Foundation
import RealmSwift

class BoardStorage {
    private let realm: Realm

    init() {
        try! realm = Realm()
    }

    func add(d :BoardData) {
        if let last = realm.objects(BoardData).sorted("id").last {
            d.id = last.id + 1
        } else {
            d.id = 1
        }
        realm.write {
            self.realm.add(d)
        }
    }

    func find(id: Int) -> BoardData? {
        return realm.objects(BoardData).filter("id = \(id)").first
    }

    func find(genre genre: String) -> [BoardData] {
        return realm.objects(BoardData).filter("genre = '\(genre)'").map { $0 }
    }

    func findAll() -> [BoardData] {
        return realm.objects(BoardData).map { $0 }
    }

    func read(id: Int) {
        if let data = find(id) {
            realm.write {
                data.read = true
            }
        }
    }

    func delete() {
        let objs = self.realm.objects(BoardData)
        realm.write {
            self.realm.delete(objs)
        }
    }
}

findまわりがちょい汚い()

EntityはBoardDataってクラス

import Foundation
import RealmSwift

class BoardData: Object {
    dynamic var id = 0
    dynamic var read = false
    dynamic var genre = ""
    dynamic var title = ""
    dynamic var updated = ""

    override class func primaryKey() -> String {
        return "id"
    }
}

こんな感じ
まだAutoIncrementは実装されてないっぽい

ハマりどころ?

そんなにハマったわけじゃないけど、無意識に実装しててエラー出たところ

1スレッド 1Realm()

Realm()でインスタンスを生成するやつ、1スレッドにつき1インスタンス生成をしなきゃいけない

見やすいようにこう定義しておく
dispatch_async_mainがメインスレッドへのキューでdispatch_async_globalが非UIスレッドへのキューみたいな感じ?

func dispatch_async_main(block: () -> ()) {
    dispatch_async(dispatch_get_main_queue(), block)
}

func dispatch_async_global(block: () -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block)
}

こういうコードは死ぬ(実際はBoardを管理するクラスを挟んだりするけどわかりやすいように)

let storage = BoardStorage()

dispatch_async_global({() -> Void in
    let boards = Board.fetchFromRemote()
    self.storage.save(boards) // >突然の死<
})

saveしてるところはBoardStorage()してるのと違うスレッドなので死ぬ

let storage = BoardStorage()

dispatch_async_global({() -> Void in
    let boards = Board.fetchFromRemote()
    let storage = BoardStorage()
    storage.save(boards)
})

こうすればRealm()はそれぞれのスレッドで呼ばれるので動く
気をつけようね><

感想

Auto Incrementが早く欲しいでござる〜
これからも使っていこう、また追記しよう