Realm Swiftメモ
swiftでエンティティの永続化をするためにRealmを触ってみたのでメモする。
あんまり詳しくないけどios, android共にアプリ内のDBはRealmがデファクトに近いらしい。
インストール
cocoapodsで入れる
初期化
pod init
Podfileを編集
target 'SampleApp' do use_frameworks! pod 'RealmSwift' end
インストール
pod install
使い方
クラスを定義
永続化したいクラスは通常の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
realmをインスタンス化する際にschemaVersionを更新すればエラーは起きなくなるが、これだけだと既存のデータは修正されない。
let realm = try! Realm(configuration: Realm.Configuration(schemaVersion: 2))
データを格納したファイルを削除することでも対応できるので、データが消えても問題ない場合はこちらの方が早い。
//ファイルの場所を取得して消す if let fileURL = Realm.Configuration.defaultConfiguration.fileURL { try! FileManager.default.removeItem(at: fileURL) }