Realm Blog

Realm Objective‑C & Swift 0.100 – クエリに指定可能で自動更新が有効な逆方向の関連をサポートしました!

Realm Objective‑CおよびRealm Swift 0.100をリリースしました。

このバージョンでは、非常に多くのリクエストをいただいていた、もうひとつの機能である、逆方向の関連について、クエリの条件に指定可能にすることと、自動更新がサポートされました。このことにより、逆方向の関連は通常の関連とまったく同様に取り扱えるようになります。

逆方向の関連がクエリの条件に指定可能、自動更新が有効

まず簡単にRealmにおいて関連がどのように機能するのかをご説明します。関連は基本的に一方向でRLMArray/Listまたはオブジェクト型のプロパティとして表現されます。これらの関連のプロパティはクエリの条件に指定することができ、アプリの別の場所で更新があっても自動的に最新の内容が反映されます。

逆方向の関連を取得するためには、Realmは以前からその時点のスナップショットを返すためのメソッドを用意していました。Realm 0.100ではその動作を改善し、逆方向の関連をLinking Objectと呼ばれるプロパティで表現することが可能になりました。このプロパティは自動更新可能で、クエリの条件に指定することができ、他のコレクション型のオブジェクトと同様にコレクションに対するクエリも使用することができます。

唯一他のプロパティと異なる点は、Linking Objectは直接変更することができないという点です。Linking Objectは正方向の関連であるRLMArray/Listまたはオブジェクト型のプロパティに変更が加えられることによって、その結果として変更されます。

1対多の関連

@interface Dog : RLMObject
@property NSString *name;
@property NSInteger age;
@property Person *owner;
@end

@implementation Dog
@end

@interface Person : RLMObject
@property NSString *name;
@property NSInteger age;
@property (readonly) RLMLinkingObjects<Dog *> *dogs;
@end

@implementation Person
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"dogs": [RLMPropertyDescriptor descriptorWithClass:Dog.class propertyName:@"owner"],
    };
}
@end
class Dog: Object {
    dynamic var name = ""
    dynamic var age = 0
    dynamic var owner: Person?
}

class Person: Object {
    dynamic var name = ""
    dynamic var age = 0
    let dogs = LinkingObjects(fromType: Dog.self, property: "owner")
}

多対多の関連

@interface Person : RLMObject
@property NSString *name;
@property NSInteger age;
@property RLMArray<Person *><Person> *children;
@property (readonly) RLMLinkingObjects<Person *> *parents;
@end

@implementation Person
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"parents": [RLMPropertyDescriptor descriptorWithClass:Person.class propertyName:@"children"],
    };
}
@end
class Person: Object {
    dynamic var name = ""
    dynamic var age = 0
    let children = List<Person>()
    let parents = LinkingObjects(fromType: Person.self, property: "children")
}

直接変更できないという性質のため、RLMLinkingObjects/LinkingObjects型のプロパティはreadonly/letとして宣言する必要があります。

新しいLinking Object型のプロパティを使うことは、これまでの方法に比べていくつか大きな利点があります。

1) Linking Objectは自動更新可能なコレクション

他のコレクション型と同様に、RLMLinkingObjects/LinkingObjectsは自動更新が働きます。新しく関連が追加されたり、削除されたりすると、Linking Objectは自動的に最新の状態を反映するように変更されます。つまり、もう必要に応じて静的なスナップショットを自分で取得する必要はありません。

2) Linking Objectはクエリの条件に使用可能

古いAPIでは逆方向の関連を使ったクエリは実行できなかったので、自分でオブジェクトをフィルタするようなコードを書く必要がありました。そのため、Realmのクエリを使用するよりはパフォーマンスが悪く、自動更新も利用できませんでした。

新しいLinking Objectは完全にRealmのクエリシステムに統合されているので、逆方向の関連に対して効率よく、簡単にフィルタを実行することができます。

// 親の名前がDianeである子を持つ人を検索する。
[PersonObject objectsWhere:@"ANY children.parents.name == 'Diane'"];

// 両親の平均年齢が65歳より高い人を検索する。
[PersonObject objectsWhere:@"[email protected] > 65"];
// 親の名前がDianeである子を持つ人を検索する。
realm.objects(Person).filter("ANY children.parents.name == 'Diane'")

// 両親の平均年齢が65歳より高い人を検索する。
realm.objects(Person).filter("[email protected] > 65")

3) Linking ObjectはRealmコレクションと同様です

かつての古いAPIは標準ライブラリの配列を返していました。新しいRLMLinkingObjects/LinkingObjects型はRealmコレクションプロトコルに準拠しています。そのため、使い慣れたRLMResults/Resultsなどと同様の機能をすべて利用することができます。

// 両親のうち56歳より年上なのはどちら?
[self.parents objectsWhere:@"age > 56"];

// 両親の平均年齢を計算する
[self.parents averageOfProperty:"age"];
// 両親のうち56歳より年上なのはどちら?
self.parents.filter("age > 56")

// 両親の平均年齢を計算する
self.parents.average("age")

非推奨となるAPI

-[RLMObject linkingObjectsOfClass:forProperty:]Object.linkingObjects(_:forProperty:)のメソッドは非推奨となります。将来のリリースでは削除される可能性があります。

その他の変更

  • 同値性を調べるクエリにおいて、複数レベルのキーパスがサポートされます。
  • RLMArray / List型のプロパティを!=を用いて比較するクエリについて、正しい結果を返すようになりました。
  • オブジェクトの通知が有効なとき、書き込みトランザクションの後でRLMArray/Listを削除するようなトランザクションが実行された場合、アサーションに失敗していた問題を修正しました。

お読みいただきありがとうございます。 Realm で素晴らしいアプリケーションを作りましょう!お困りの際はStack Overflow(日本語)Slack(日本語)Twitter(日本語)GitHub(英語)でご相談ください。


Realm Team

At Realm, our mission is to help developers build better apps faster. We provide a unique set of tools and platform technologies designed to make it easy for developers to build apps with sophisticated, powerful features — things like realtime collaboration, augmented reality, live data synchronization, offline experiences, messaging, and more.

Everything we build is developed with an eye toward enabling developers for what we believe the mobile internet evolves into — an open network of billions of users and trillions of devices, and realtime interactivity across them all.

記事の更新情報を受け取る