LoginSignup
15
16

More than 5 years have passed since last update.

RealmのIDを自動採番(オートインクリメント)する方法

Posted at

はじめに

Realmにはauto incrementの機構がありません。
なので、僕なりに工夫したことを残しておきます。

なお、本コードはスレッドセーフで使うことを前提としています。
もし、非同期で同時のタイミングで保存する可能性がある場合はsynchronizedなどの処理を施してください。

コード

何はともあれコードは以下になります。

class RObject: Object {
    // ID
    dynamic var id = 0

    // データを保存。
    func save() {
        let realm = try! Realm()
        if realm.isInWriteTransaction {
            if self.id == 0 { self.id = self.createNewId() }
            realm.add(self, update: true)
        } else {
            try! realm.write {
                if self.id == 0 { self.id = self.createNewId() }
                realm.add(self, update: true)
            }
        }
    }

    // 新しいIDを採番します。
    private func createNewId() -> Int {
        let realm = try! Realm()
        return (realm.objects(type(of: self).self).sorted(byKeyPath: "id", ascending: false).first?.id ?? 0) + 1
    }

    // プライマリーキーの設定
    override static func primaryKey() -> String? {
        return "id"
    }
}

使い方

Modelオブジェクトを以下のように定義します。

class User: RObject {
    // 名前
    dynamic var name = ""
}

上記のクラスを保存する場合

let user = User()
user.name = "hoge"
user.save()

更新もしくは新規登録する場合

let realm = try! Realm()
let user = realm.objects(User.self).first ?? User()
try! realm.write {
    user.name = "hoge"
    user.save()
}

最後に

この方法を使えば全てのオブジェクトにidが自動的に付与されるのでRailsのように使えます。(言い過ぎ
注意点として、現在のバージョン(2.5.0)の時点では親子関係があってもキャストができないので注意。
RObjectにキャストすることはないと思いますが、、、念のため)

15
16
0

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
15
16