UKey's Labo

値の更新(update)

慣れると大した事ないけど、はじめは戸惑うこの仕様。

動作環境

環境 バージョン
Xcode 9.4.1
iOS 11.4
swift 4.1.2
Realm 3.1.1

SQLのupdate文との違い

ついついRDB感覚で、値を更新(update)となると、

と考えてしまうのですが、若干感覚が異なります。 考え方の大筋は問題ないですが。

ついやってしまう過ち

updateする際は、まずテーブルにデータを探しに行きます。

// 更新対象のデータを取得
let item: Item = itemInteractor.selectById(id: itemId)

ここで使ってるselectById()はこんな定義で、1件のみ取得します。

func selectById(itemId iId: Int) -> Item()? {
    let predicate: NSPredicate = NSPredicate(format: "itemId = %d", iId)
    let results: Results<Item> = realm.objects(Item.self).filter(predicate)
    if results > 0 {
        return results[0]
    }
    return nil

画面でユーザが値を変更したら、取得データを書き換え。

item.name = itemName

しかし!

これをやると以下のようなエラーが出力される。

Attempting to modify object outside of a write transaction

Terminating app due to uncaught exception 'RLMException', reason: 'Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.'

トランザクション外で値書き換えんじゃねぇよと怒られます。

実際の変更方法

ということなので、トランザクション内で書き換えてあげましょう。

let realm: Realm = try! Realm()
// 書き込みトランザクション開始
try! realm.write {
    item.name = itemName
}

これでOKです。

一旦、realmに追加、保存したデータはマネージドオブジェクトとなり、Realmの監視対象となってしまうため、トランザクション外で書き換えを行うと、exceptionが発生します。

[amazon_link asins=’4774188484′ template=’custom’ store=’takayuki57101-22′ marketplace=’JP’ link_id=’41b59a0e-a3c7-11e8-8153-15a7dfbcc5b7′]