Help us understand the problem. What is going on with this article?

Realmメモ

More than 3 years have passed since last update.

スレッド間のオブジェクト共有不可能

一意に検索できるものを渡して別スレッド上で再検索し、オブジェクトを生成する。

let realm = try! Realm()
let foo1 = realm.objects(Foo).first!
let fooId = foo1.id
let q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(q) {
    let foo2 = realm.objects(Foo).filter("id = %@", fooId).first!
    print(foo2.name) // ok
    print(foo1.name) // error
}

オブジェクトを削除すると関連している箇所はnilになる

class Foo: Object {
    dynamic var id = NSUUID().UUIDString
    dynamic var bar: Bar?
    let bazList = List<Baz>()
}

class Bar: Object {
    dynamic var id = NSUUID().UUIDString
}

class Baz: Object {
    dynamic var id = NSUUID().UUIDString
}

let realm = try! Realm()
let bar = Bar()
let baz = Baz()
let foo = Foo(value: ["bar": bar, "baz": baz])
realm.write {
    realm.add(bar)
    realm.add(baz)
    realm.add(foo)

    realm.delete(bar)
    realm.delete(baz)
}

print(foo.bar) // nil
print(foo.bazList.count) // 0

Realm#delete()はSequenceTypeなものは入る

Realm Docsのオブジェクトの削除にはオブジェクト単体かDB内全削除しか例にないが、 delete() の定義を見ると

public func delete<S: SequenceType where S.Generator.Element: Object>(objects: S)

があるので、次のように同時に複数のオブジェクトを削除することもできる。

// 検索結果を利用して削除
realm.delete(realm.objects(Foo).filter("id IN %@", ["a", "b"]))

// 関連しているオブジェクトを削除
realm.delete(foo.bazList)

LinkingObjectsは遅延解決

Realmにおけるオブジェクト間の関係は一方向なので、本来は両方に別オブジェクトへの関係を書かないといけないのだが、大きくなればなるほど整合性を保つのが大変になる。
そのために存在するのが LinkingObjects である。

class Foo: Object {
    dynamic var name = ""
    dynamic var bar: Bar?
}

class Bar: Object {
    dynamic var name = ""
    let fooList = LinkingObjects(fromType: Foo.self, property: "bar")
}

ただし、LinkingObjectsはリストのようなものなので、OneToOneのような関係の場合は次のように書いてしまいがち。

class Bar: Object {
    let foo = LinkingObjects(fromType: Foo.self, property: "bar").first!
}

これは必ずnilになる。
なぜかというと、LinkingObjectsはオブジェクトが生成されてから意味を持つオブジェクトなので、それまでは何のデータもないオブジェクトになるから。

もし単体で欲しい場合は、次のように書く必要がある。

public class Bar: Object {
    private let fooList = LinkingObjects(fromType: Foo.self, property: "bar")
    public var foo: Foo { return fooList.first! }
}

データモデルへの変更はリアルタイム

Realmの更新は全てトランザクション内でないといけないので

let foo = realm.objects(Foo.self).first!
foo.name = "foo"
try! realm.write { realm.add(foo, update: true) }

とかやろうとするとfoo.name = "foo"の時点でエラーになるので、次のようにトランザクション内で全て行う必要がある。

let foo = realm.objects(Foo.self).first!
try! realm.write {
    foo.name = "foo"
}

結局Realmオブジェクトを剥き出しにしないとならなくなるので、何かのクラス内に押し込めたく考えた結果、次のような方法で更新処理をするようにした。

let foo = Foo(value: realm.objects(Foo.self).first!)
foo.name = "foo"
try! realm.write { realm.add(foo, update: true) }

Fooにはちゃんとプライマリーキーを設定しないといけない。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした