(WIP)Realm Swiftメモ

swiftでエンティティの永続化をするためにealmを触ってみたのでメモする。
あんまり詳しくないけどios, android共にアプリ内のDBはRealmがデファクトに近いらしい。

インストール

cocoapodsで入れる

初期化
pod init
Podfileを編集
target 'SampleApp' do
  use_frameworks!
  pod 'RealmSwift'
end
インストール
pod install

使い方

※基本チュートリアルに書いてある内容 realm.io

クラスを定義

永続化したいクラスは通常のSwiftのクラスと同じように定義する。
realmで永続化するクラス同士のリレーションを持たせたい時には通常のクラスと同じようにプロパティに追加する。
リレーションはoptionalにしておかないとRLMExceptionが発生し "Item.user" property must be marked as being optional と言われる。

import RealmSwift

final class Item: Object {
    dynamic var id: String
    dynamic var title: String
    dynamic var description: String
    dynamic var user: User?
    
    //primaryKeyを定義
    override static func primaryKey() -> String? {
        return "id"
    }
}

final class User: Object {
    dynamic var id: String
    dynamic var name: String
    
    override static func primaryKey() -> String? {
        return "id"
    }
}
更新系の処理
//インスタンス化
let realm = try! Realm()

//追加
let item = Item(value["id": "a1", "title": "hogehoge", "description": "hugahuga"]
)
item.user = User(value["id": "b1", "title": "piyopiyo"])

try! realm.write() {
    realm.add(item)
}

//更新
try! realm.write() {
   item.title = "hogehoge2"
   item.description = "hugahuga2"
}

//削除
try! realm.write() {
    realm.delete(item)
}
参照系の処理
//全件取得
let items = Array(realm.objects(Item.self))   //Result型からArray型にする

//検索
let items = Array(realm.objects(Item.self).filter("name = hogehoge"))

//関連オブジェクトから検索
let items = Array(realm.objects(Item.self).filter("user.name = piyopiyo"))

変数を埋め込む際は下記のようにする。
普通の文字列に変数を埋め込むやり方をするとエラーになってしまう。(内部でNSPredicateを使用しているため。)

//変数を使って検索
let items = Array(realm.objects(Item.self).filter("name = %@", itemName))

//これは失敗する
let items = Array(realm.objects(Item.self).filter("name = \(itemName)"))

マイグレーション

既存のクラスに破壊的変更を加えた場合、実行時にエラーが発生する。 解消するにはマイグレーションを行う必要がある。
https://realm.io/jp/docs/swift/latest/#migrations

データを格納したファイルを削除することでも対応できるので、データが消えても問題ない場合はこちらの方が早い。

//ファイルの場所を取得して消す
if let fileURL = Realm.Configuration.defaultConfiguration.fileURL {
    try! FileManager.default.removeItem(at: fileURL)
}