9010

[code]

    if let posts = Post.objectsWithPredicate(NSPredicate(format: "active == FALSE")) as RLMResults? {
        realm.beginWriteTransaction()
        for postObj in posts {
            if let post = postObj as? Post {
                post.active = true
            }
        }
        realm.commitWriteTransaction()
    }
    
[/code]

例えばこのような更新処理があったとした場合に、更新が1つ飛ばしずつしかできなくなります。  
理由としては、RLMResultsが常に最新状態になるため、post.active=trueするたびにpostsからオブジェクトがなくなっていくことが原因だと思われます。

このような場合にはどのような書き方をすることで、適切に全てのレコードを更新できるのでしょうか？


CC BY-SA 3.0
2015-04-10T09:07:05.353
9004
2015-04-10T10:32:30.220
2015-04-10T10:32:30.220
5519
2772
question
swift realm
RealmでRLMResultsをfor inで更新するときに一つ飛ばしになってしまう問題について


おっしゃる通り、`RLMResults`が変更を即座に反映するためにそのような挙動になります。  
これは便利な部分ではあるのですが、このようにすべての要素をループして変更する際に直感的でない場合があります。

望みの動作に修正するには、次のように`while`ループを使用します。`posts`のカウントは`post.active`プロパティが変更されると即座に数が減るのでこのように書くことで全件の更新ができます。

[code]

    let posts = Post.objectsWhere("active == FALSE")
    realm.transactionWithBlock {
        while posts.count > 0 {
            if let post = posts.firstObject() as? Post {
                post.active = true
            }
        }
    }
    
[/code]

ちなみに、次にリリースされるバージョンでは [こちらの変更 (https://github.com/realm/realm-
cocoa/pull/1536)](https://github.com/realm/realm-cocoa/pull/1536)
により全てのオブジェクトに対する更新はもっと簡単に `posts.setValue(false, forKey: "active")`
と書けるようになります。

あと、細かいことですが、`objectsWithPredicate()`メソッドはObjective-
Cのメソッドなので、戻り値が`RLMResults!`とOptionalになってしまいますが、`RLMSupport.swift`ファイルを追加して、`objectsWhere()`を使えるようにすると、戻り値の型は`RLMResults`になり、`nil`が返ることはありませんので、`if
let`でバインディングする必要がなくなります。


CC BY-SA 3.0
2015-04-10T10:12:28.580
9010
2015-04-10T10:12:28.580
5519
9004
answer