对关系建模 - Swift SDK
声明关系属性
定义对一关系属性
一对一关系将一个属性映射到另一种对象类型的单个实例。例如,您可以将一个最多有一只伴侣犬的人建模为一对一的关系。
将关系字段设置为 null 会删除对象之间的连接。 但是,Realm 不会删除引用的对象,除非它是嵌入式对象。
重要
对一关系必须是可选的
在对象模型中声明对一关系时,它必须是一个可选属性。如果您尝试建立所需的对一关系,Realm 会在运行时引发异常。
// Dog.h @interface Dog : RLMObject @property NSString *name; // No backlink to person -- one-directional relationship @end // Define an RLMArray<Dog> type RLM_COLLECTION_TYPE(Dog) // Person.h @interface Person : RLMObject @property NSString *name; // A person can have one dog @property Dog *dog; @end // Dog.m @implementation Dog @end // Person.m @implementation Person @end
class Person: Object { var name: String = "" var birthdate: Date = Date(timeIntervalSince1970: 1) // A person can have one dog var dog: Dog? } class Dog: Object { var name: String = "" var age: Int = 0 var breed: String? // No backlink to person -- one-directional relationship }
提示
另请参阅:
有关对一关系的更多信息,请参阅:对一关系。
如果您的应用程序使用 Device Sync,请参阅使用 Device Sync 的模型数据页面,了解有关 Swift 对象模型中的一对一关系如何转换为 Atlas 文档的信息。
定义对多关系属性
一/多对多关系可将一个属性映射到其他对象类型的零个或多个实例。例如,您可将拥有任意数量伴侣犬的一个人构建为一/多对多关系。
使用标有目标类型的RLMArray来定义对多关系属性。
提示
请记住将 RLM_COLLECTION_TYPE()
宏与您的类型一起使用,以声明您类型的 RLMArray协议。
// Dog.h @interface Dog : RLMObject @property NSString *name; // No backlink to person -- one-directional relationship @end // Define an RLMArray<Dog> type RLM_COLLECTION_TYPE(Dog) // Person.h @interface Person : RLMObject @property NSString *name; // A person can have many dogs @property RLMArray<Dog *><Dog> *dogs; @end // Dog.m @implementation Dog @end // Person.m @implementation Person @end
使用标有目标类型的列表来定义您的多对多关系属性。
class Person: Object { var name: String = "" var birthdate: Date = Date(timeIntervalSince1970: 1) // A person can have many dogs var dogs: List<Dog> } class Dog: Object { var name: String = "" var age: Int = 0 var breed: String? // No backlink to person -- one-directional relationship }
提示
另请参阅:
有关对多关系的更多信息,请参阅:对多关系。
如果您的应用使用 Device Sync,请参阅使用 Device Sync 的模型数据页面,了解有关 Swift 对象模型中的一对多关系如何转换为 Atlas 文档的信息。
定义反向关系属性
反向关系属性是一种自动反向链接关系。每当在对应的一对多列表或一对一关系属性中添加或删除对象时,Realm 都会自动更新隐式关系。无法手动设置反向关系属性的值。
要定义反向关系,请使用对象模型中的LinkingObjects 。 LinkingObjects
定义指定了反向关系的对象类型和属性名称。
class User: Object { true) var _id: ObjectId (primaryKey: var _partition: String = "" var name: String = "" // A user can have many tasks. var tasks: List<Task> } class Task: Object { true) var _id: ObjectId (primaryKey: var _partition: String = "" var text: String = "" // Backlink to the user. This is automatically updated whenever // this task is added to or removed from a user's task list. "tasks") var assignee: LinkingObjects<User> (originProperty: }
要定义反向关系,请在对象模型中使用RLMLinkingObjects 。 覆盖类中的+[RLMObject LinkingObjectProperties]方法,以指定其反向关系的对象类型和属性名称。
// Task.h @interface Task : RLMObject @property NSString *description; @property (readonly) RLMLinkingObjects *assignees; @end // Define an RLMArray<Task> type RLM_COLLECTION_TYPE(Task) // User.h @interface User : RLMObject @property NSString *name; @property RLMArray<Task *><Task> *tasks; @end // Task.m @implementation Task + (NSDictionary *)linkingObjectsProperties { return @{ @"assignees": [RLMPropertyDescriptor descriptorWithClass:User.class propertyName:@"tasks"], }; } @end // User.m @implementation User @end
要定义反向关系,请使用对象模型中的LinkingObjects 。 LinkingObjects
定义指定了反向关系的对象类型和属性名称。
class User: Object { @objc dynamic var _id: ObjectId = ObjectId.generate() @objc dynamic var _partition: String = "" @objc dynamic var name: String = "" // A user can have many tasks. let tasks = List<Task>() override static func primaryKey() -> String? { return "_id" } } class Task: Object { @objc dynamic var _id: ObjectId = ObjectId.generate() @objc dynamic var _partition: String = "" @objc dynamic var text: String = "" // Backlink to the user. This is automatically updated whenever // this task is added to or removed from a user's task list. let assignee = LinkingObjects(fromType: User.self, property: "tasks") override static func primaryKey() -> String? { return "_id" } }
提示
另请参阅:
有关反向关系的更多信息,请参阅:反向关系。
如果您的应用使用了 Device Sync,则请参阅使用 Device Sync 进行数据建模页面,以了解有关如何将 Swift 对象模型中的逆关系转换为 Atlas 文档的信息。
定义嵌入式对象属性
嵌入式对象将作为单个特定父对象内部的嵌套数据而存在。它会继承其父对象的生命周期,但无法作为独立 Realm 对象存在。如果嵌入式对象的父对象被删除或被新的嵌入式对象实例覆盖,Realm 则会自动删除嵌入式对象。
注意
Realm 对嵌入式对象使用级联删除
您可以通过从RLMEmbeddedObject类派生来定义嵌入式对象。 您可以像使用任何其他类型一样在另一个模型中使用嵌入式对象。
// Define an embedded object @interface Address : RLMEmbeddedObject @property NSString *street; @property NSString *city; @property NSString *country; @property NSString *postalCode; @end // Enable Address for use in RLMArray RLM_COLLECTION_TYPE(Address) @implementation Address @end // Define an object with one embedded object @interface Contact : RLMObject @property NSString *name; // Embed a single object. @property Address *address; @end @implementation Contact @end // Define an object with an array of embedded objects @interface Business : RLMObject @property NSString *name; // Embed an array of objects @property RLMArray<Address *><Address> *addresses; @end
您可以通过从 EmbeddedObject 类派生来定义嵌入式对象。您可以像使用任何其他类型一样在另一个模型中使用嵌入对象。
class Person: Object { true) var id = 0 (primaryKey: var name = "" // To-many relationship - a person can have many dogs var dogs: List<Dog> // Inverse relationship - a person can be a member of many clubs "members") var clubs: LinkingObjects<DogClub> (originProperty: // Embed a single object. // Embedded object properties must be marked optional. var address: Address? convenience init(name: String, address: Address) { self.init() self.name = name self.address = address } } class DogClub: Object { var name = "" var members: List<Person> // DogClub has an array of regional office addresses. // These are embedded objects. var regionalOfficeAddresses: List<Address> convenience init(name: String, addresses: [Address]) { self.init() self.name = name self.regionalOfficeAddresses.append(objectsIn: addresses) } } class Address: EmbeddedObject { var street: String? var city: String? var country: String? var postalCode: String? }