模型数据 - Swift SDK
对象类型和模式
Realm 应用程序将数据视为对象进行建模,每个对象由字段与值配对组成,每一对都包含一种或多种支持的数据类型。
Realm对象是常规的 Swift 或Objective-C类,但它们也带来了一些附加功能,例如 实时查询 。 Swift SDK内存将Realm对象直接映射到原生Swift 或Objective-C对象,这意味着无需使用特殊的数据访问库,例如 ORM 。相反,您可以像使用任何其他类实例一样使用Realm对象。
每个 Realm 对象都遵循特定的对象类型。对象类型本质上是一个定义该类型对象的属性和关系的类。域保证所有 Realm 对象都符合对象类型的模式,并在创建、修改或删除对象时对其进行验证。
例子
以下模式定义了一个 Dog
对象类型,其中包含字符串名称、可选字符串品种、出生日期和主键 ID。
// A dog has an _id primary key, a string name, an optional // string breed, and a date of birth. @interface Dog : RLMObject @property RLMObjectId *_id; @property NSString *name; @property NSString *breed; @property NSDate *dateOfBirth; @end @implementation Dog + (NSString *)primaryKey { return @"_id"; } + (NSArray<NSString *> *)requiredProperties { return @[ @"_id", @"name", @"dateOfBirth" ]; } @end
// A dog has an _id primary key, a string name, an optional // string breed, and a date of birth. class Dog: Object { true) var _id: ObjectId (primaryKey: var name = "" var breed: String? var dateOfBirth = Date() }
Realm 模式
Realm 模式是 Realm 可能包含的有效对象模式的列表。 每个 Realm 对象都必须符合其 Realm 模式中包含的对象类型。
默认情况下,Swift SDK 会自动将项目中源自 RLMObject 或 RLMEmbeddedObject 的所有类添加到域模式中。
如果 Realm 在打开时已包含数据,Realm 则会验证每个对象以确保为其类型提供了对象模式,且它满足该模式中指定的所有约束。
模型继承
您可以对 Realm 模型进行子类化,以便在类之间共享行为,但这样操作会受到一些限制。特别是,Realm 不允许:
多态类之间的转换:子类转换成子类,子类转换成父类,父类转换成子类
同时查询多个类:例如,“获取父类和子类的所有实例”
多类容器:
List
和Results
,混合了父类和子类
提示
查看代码示例,以解决这些限制。
版本 10.10.0 中的新增功能:虽然您不能在一个类中混合使用 @Persisted
和 @objc dynamic
属性声明,但您可以在基类和子类之间混合符号样式。例如,基类可以具有 @Persisted var foo: Int
属性,子类可以具有 @objc dynamic var bar = 0
属性,两者都可以持久化。但是,如果 @Persisted
属性在同一基类或子类中,则将忽略 @objc dynamic
属性。
Swift 结构体
由于多种原因,Realm 不支持将 Swift 结构体作为模型。Realm 的设计侧重于“活动”对象。此概念与值类型结构体不兼容。根据设计,Realm 提供的功能与以下语义不兼容,例如:
数据占用内存少
良好的操作性能
缺乏数据序列化/反序列化
也就是说,在某些情况下,将对象与其支持 Realm 分离是非常有用的。通常情况下,这并非一个理想的设计决策。相反,开发者将其视为一种解决库中临时限制的变通方法。
您可以使用键值编码将非托管对象初始化为托管对象的副本。 然后,您可以像使用任何其他 NSObject 一样使用该非托管对象。
let standaloneModelObject = MyModel(value: persistedModelObject)
属性
您的 Realm 对象模型是属性的集合。在最基本的层面上,当您创建模型时,您的声明会提供有关每个属性的 Realm 信息:
数据类型以及属性是可选还是必需
Realm 应存储还是忽略该属性
属性是主节点还是应编入索引
属性同时也是在不同 Realm 对象类型之间构建关系的机制。
Realm Swift SDK 使用反射来确定模型的运行时属性。您的项目不得设置 SWIFT_REFLECTION_METADATA_LEVEL = none
,否则 Realm 无法发现属性和枚举等类型的子类型。如果您的项目未专门为此设置设定级别,则默认情况下会启用反射。
使用 Realm 查看模型
10.21.0 版新增功能。
您可以通过创建类投影来使用 Realm 对象属性的子集。类投影是一种类,用于传递或转换 Realm 对象的部分或全部属性。类投影可以帮助您构建使用对象模型抽象的视图模型。这简化了应用程序中 Realm 对象的使用和测试。
通过类投影,可直接在用户界面中使用对象属性的子集或对其进行转换。为此目的而使用类投影时,可享受到 Realm 活动对象的所有好处:
类投影对象实时更新
您可以观察它的变化
您可以将更改直接应用于写事务中的属性
关系
在定义关系时,Realm 不采用关系数据库中的桥接表或显式联接方式。Realm 通过嵌入式对象或其他 Realm 对象的引用属性来处理关系。您可以直接读取和写入这些属性。因此,查询关系与查询其他属性一样高效。
Realm 支持对一、对多和反向关系。
对一关系
对一关系是指一个对象与另一个对象相关。您可以在对象类型的对象模式中为其定义对一关系。指定一个属性。其中,类型是相关的 Realm 对象类型。例如,狗可能与最喜欢的玩具存在对一关系。
提示
要了解如何定义对一关系,请参阅定义对一关系属性。
对多关系
对多关系是指一个对象与多个其他对象相关。在 Realm 中,对多关系是对其他对象的引用列表。例如,一个人可能会养很多只狗。
列表表示两个Realm类型之间的对多关系。 列表是可变的:在写事务(write transaction)中,您可以向列表添加元素或从列表中删除元素。 列表与查询无关,通常声明为对象模型的属性。
提示
要了解如何定义对多关系,请参阅定义对多关系属性。
反向关系
Realm 中的关系定义是单向的。反向关系将对象链接回引用它的对象。您必须在对象模型中明确将属性定义为反向关系。反向关系可以链接回对一或对多关系中的对象。
LinkingObjects集合表示两个Realm类型之间的反向关系。 您不能直接在 LinkingObjects集合中添加或删除项目。
逆向关系会自动使用相应的反向链接进行更新。您可以通过手动查询查找同一组 Realm 对象,但使用逆向关系字段可以减少样板查询代码和出错的可能性。
例如,假设一个具有多对多关系的任务跟踪器 “用户有许多任务”。 这不会自动创建逆关系“任务属于用户”。 要创建反向关系,可在任务上添加一个用户属性,指向任务的所有者。 当您指定从任务到用户的反向关系时,您可以对其进行查询。 如果未指定反向关系,则必须运行单独的查询,查找向其分配任务的用户。
重要
无法手动设置反向关系属性的值。相反,每当您添加或删除相关对象时,Realm 会更新隐式关系。
关系可以是多对一或多对多。因此,遵循反向关系可能会得到零个、一个或多个对象。
提示
要了解如何定义逆向关系,请参阅定义逆向关系属性。