Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ /

支持的类型 - Swift SDK

Realm 有多种类型来表示对象组,而我们将其称为集合。集合是指包含零个或多个某种 Realm 类型实例的对象。Realm 集合具有同质性:集合中的所有对象均为同一类型。

您可以使用 Realm 的查询引擎对任意集合进行筛选和排序。集合为实时对象,因此它们始终会反映当前线程上 Realm 实例的当前状态。此外,还可通过订阅集合通知来侦听集合中的更改。

所有集合类型都符合 RealmCollection 协议。此协议继承自 CollectionType ,因此您可以像使用任何其他标准库集合一样使用Realm集合。

通过使用 RealmCollection 协议,您可以编写可对任意 Realm 集合进行操作的通用代码:

func operateOn<C: RealmCollection>(collection: C) {
// Collection could be either Results or List
print("operating on collection containing \(collection.count) objects")
}

Swift SDK结果集合是一个表示从查询中检索到的对象的类。 结果集合表示查询操作的延迟计算结果。 结果是不可变的:您不能在结果集合中添加或删除元素。 结果具有确定其内容的关联查询。

Swift SDK还提供了SectionedResults ,这是一个类型安全的集合,其中包含 ResultsSection作为其元素。 每个ResultSection都是一个结果集合,其中仅包含属于给定部分键的对象。

例如,包含联系人列表的应用程序可能会使用SectionedResults 来显示划分为多个节的联系人列表,其中每个节均包含名字以给定字母开头的所有联系人。键为“L”的 ResultsSection 将包含“Larry”、“Liam”和“Lisa”。

提示

Swift SDK 还提供多种集合类型,而您可将其用作个人数据模型中的属性:

  1. List ,一个表示模型中对多关系的类。

  2. LinkingObjects ,一个表示模型中反向关系的类。

  3. MutableSet ,表示对多关系的类。

  4. Map ,一个类,表示具有唯一键的键值对关联数组。

  5. AnyRealmCollection 类型擦除的 类,它可以将调用转发到具体的 Realm 集合,例如 Results、List 或 LinkingObjects。

活动对象一样,Realm 集合通常也为实时集合:

  • 实时结果集合始终会反映关联查询的当前结果。

  • 实时列表始终会反映 Realm 实例关系的当前状态。

集合在两种情况下处于实时状态:

  • 集合为非托管集合。例如,尚未添加到 Realm 或已从 Realm 复制的 Realm 对象的 List 属性便处于非实时状态。

  • 集合已被冻结

集合通知相结合时,实时集合可实现简洁的响应式代码。例如,假设您的视图会显示查询结果。您可在视图类中保留对结果集合的引用,然后按需读取结果集合,而不必刷新该集合或验证其是否处于最新状态。

重要

结果索引可能会发生变化

由于结果会自动更新自身,因此请勿存储集合中对象的位置索引或集合中对象的数量。存储的索引或数量值在您使用时可能已过期。

您可以使用以下类型来定义对象模型属性。

要了解如何将特定数据类型映射到 App Services 模式中的 BSON 类型,请参阅 Atlas App Services 文档中的数据模型映射

另请参阅使用 Device Sync 对数据建模 - Swift SDK。

在版本 10.10.0 中进行了更改@Persisted 属性声明语法

类型
必需
Optional

bool

@Persisted var boolName: Bool
@Persisted var optBoolName: Bool?

Int、Int8、Int16、Int32、Int64

@Persisted var intName: Int
@Persisted var optIntName: Int?

Float

@Persisted var floatName: Float
@Persisted var optFloatName: Float?

double

@Persisted var doubleName: Double
@Persisted var optDoubleName: Double?

字符串

@Persisted var stringName: String
@Persisted var optStringName: String?

数据

@Persisted var dataName: Data
@Persisted var optDataName: Data?

Date

@Persisted var dateName: Date
@Persisted var optDateName: Date?

Decimal128

@Persisted var decimalName: Decimal128
@Persisted var optDecimalName: Decimal128?
@Persisted var uuidName: UUID
@Persisted var optUuidName: UUID?
@Persisted var objectIdName: ObjectId
@Persisted var optObjectIdName: ObjectId?
@Persisted var listName: List<MyCustomObjectType>

不适用

@Persisted var mutableSetName: MutableSet<String>

不适用

@Persisted var mapName: Map<String, String>

不适用

@Persisted var anyRealmValueName: AnyRealmValue

不适用

用户定义的对象

不适用

@Persisted var optObjectPropertyName: MyCustomObjectType?

用户定义的 EmbeddedObject

不适用

@Persisted var optEmbeddedObjectPropertyName: MyEmbeddedObjectType?

用户定义的 Enums

@Persisted var enumName: MyPersistableEnum
@Persisted var optEnumName: MyPersistableEnum?

CGFloat 属性不鼓励使用,因为此类型与平台无关。

要在 @Persisted 语法中将键值编码与用户定义的对象结合使用,请添加 @objc 属性:@Persisted @objc var myObject: MyClass?

使用 @Persisted 属性声明语法,在为以下属性设置默认值时可能会影响性能:

  • List

  • MutableSet

  • Dictionary

  • Decimal128

  • UUID

  • ObjectId

@Persisted var listProperty: List<Int>@Persisted var listProperty = List<Int>()都是有效的,并且在功能上等效。 但是,第二种声明会导致性能下降。

这是因为 List 是在创建父对象时创建的,而不是按需延迟创建的。对于大多数类型来说,这种差异太小了,因此无法测量。对于此处列出的类型,使用第二种声明样式时可能会对性能产生影响。

类型
必需
Optional

布尔

@property BOOL boolName;
@property NSNumber<RLMBool> *optBoolName;

整型

@property int intName;
@property NSNumber<RLMInt> *optIntName;

Float

@property float floatName;
@property NSNumber<RLMFloat> *optFloatName;

double

@property double doubleName;
@property NSNumber<RLMDouble> *optDoubleName;

字符串

@property NSString *stringName;
@property NSString *optStringName;

数据

@property NSData *dataName;
@property NSData *optDataName;

Date

@property NSDate *dateName;
@property NSDate *optDateName;

Decimal128

@property RLMDecimal128 *decimalName;
@property RLMDecimal128 *optDecimalName;

NSUUID

@property NSUUID *uuidName;
@property NSUUID *optUuidName;
@property RLMObjectId *objectIdName;
@property RLMObjectId *optObjectIdName;
@property RLMArray<MyObject *><MyObject> *arrayName;

不适用

@property RLMSet<RLMString> *setName;

不适用

@property RLMDictionary<NSString *, NSString *><RLMString, RLMString> *dictionaryName;

不适用

用户定义的RLMObject

不适用

@property MyObject *optObjectPropertyName;

用户定义的RLMEmbeddedObject

不适用

@property MyEmbeddedObject *optEmbeddedObjectPropertyName;

此外:

  • 整数类型intNSIntegerlonglong long

CGFloat 属性不鼓励使用,因为此类型与平台无关。

10.8.0 版本中的更改RealmProperty 取代了 RealmOptional

类型
必需
Optional

bool

@objc dynamic var value = false
let value = RealmProperty<Bool?>()

Int、Int8、Int16、Int32、Int64

@objc dynamic var value = 0
let value = RealmProperty<Int?>()

Float

@objc dynamic var value: Float = 0.0
let value = RealmProperty<Float?>()

double

@objc dynamic var value: Double = 0.0
let value = RealmProperty<Double?>()

字符串

@objc dynamic var value = ""
@objc dynamic var value: String? = nil

数据

@objc dynamic var value = Data()
@objc dynamic var value: Data? = nil

Date

@objc dynamic var value = Date()
@objc dynamic var value: Date? = nil

Decimal128

@objc dynamic var decimal: Decimal128 = 0
@objc dynamic var decimal: Decimal128?
@objc dynamic var uuid = UUID()
@objc dynamic var uuidOpt: UUID?
@objc dynamic var objectId = ObjectId.generate()
@objc dynamic var objectId: ObjectId?
let value = List<Type>()
let value = MutableSet<Type>()
let value = Map<String, String>()
let value = RealmProperty<AnyRealmValue>()

不适用

用户定义的对象

不适用

@objc dynamic var value: MyClass?

此外:

您可以使用RealmProperty <T?>来表示整数、双精度和其他可选类型。

CGFloat 属性不鼓励使用,因为此类型与平台无关。

10.8.0 版新增功能UUID 类型

ObjectId 为特定于 MongoDB 的 12 字节唯一值。UUID 为 16 字节的全局唯一值。您可为这两种类型创建索引,并将其中任一用作主键。

注意

@Persisted UUID 或 ObjectId 属性声明默认值时,以下两种语法类型均有效:

  • @Persisted var value: UUID

  • @Persisted var value = UUID()

但是,第二种语法会导致性能降低。这是因为后者会创建一个新标识符,但每次从 Realm 读取对象时均不会使用该标识符,而前者仅会在需要时创建它们。

@Persisted var id: ObjectId 具有与 @objc dynamic var _id = ObjectId.generate() 等效的行为。它们都会创建随机 ObjectId。

@Persisted var _id = ObjectId() 具有与 @objc dynamic var _id = ObjectId() 等效的行为。它们均会创建用零初始化的 ObjectId。

数据和字符串属性的容量不得超过 16 MB。要存储更大容量的数据,则可:

  • 将此数据分解为 16 MB 的数据段,或者

  • 将数据直接存储在文件系统上,并存储 Realm 中文件的路径。

如果您的应用尝试在单个属性中存储超过 16 MB 的数据,Realm 则会引发运行时异常。

为避免大小限制和性能影响,最好请勿将大型 Blob(例如图像和视频文件)直接存储在 Realm 中。相反,请将此文件保存到文件存储,并仅保留此文件的位置以及 Realm 中的所有相关元数据。

要将集合存储为属性或变量而无需知道具体的集合类型,Swift 的类型系统需要一种擦除类型的封装器,如 AnyRealmCollection:

class ViewController {
// let collection: RealmCollection
// ^
// error: protocol 'RealmCollection' can only be used
// as a generic constraint because it has Self or
// associated type requirements
//
// init<C: RealmCollection>(collection: C) where C.ElementType == MyModel {
// self.collection = collection
// }
let collection: AnyRealmCollection<MyModel>
init<C: RealmCollection & _ObjcBridgeable>(collection: C) where C.ElementType == MyModel {
self.collection = AnyRealmCollection(collection)
}
}

10.8.0 版本新增

MutableSet集合表示包含不同值的对多关系MutableSet支持以下类型(及其可选版本):

  • bool

  • 数据

  • Date

  • Decimal128

  • double

  • Float

  • Int

  • Int8

  • Int16

  • Int32

  • Int64

  • 对象

  • ObjectId

  • 字符串

  • UUID

就像 Swift 的 SetMutableSet 是一种泛型类型,会根据其存储的类型进行参数化。与 原生 Swift 集合 不同 ,Realm 可变集是引用类型,而不是值类型(结构体)。

您只能在写入事务期间调用 MutableSets 更改方法。因此,如果将管理 Realm 作为只读 Realm 打开,MutableSets 则不可变。

您可以使用与MutableSet 结果 相同的谓词 对 进行筛选和排序。与其他 Realm 集合一样,您可以在MutableSet注册变更侦听器。

例如,一个 Dog 类模型可能包含一个用于 citiesVisitedMutableSet

class Dog: Object {
@Persisted var name = ""
@Persisted var currentCity = ""
@Persisted var citiesVisited: MutableSet<String>
}

注意

@Persisted MutableSet 属性声明默认值时,以下两种语法类型均有效:

  • @Persisted var value: MutableSet<String>

  • @Persisted var value = MutableSet<String>()

但是,第二种语法会导致性能大幅下降。这是因为 MutableSet 是在创建父对象时创建的,而不是按需延迟创建的。

10.8.0 版本新增

Map是一个关联数组,其中包含具有唯一键的键值对。

就像 Swift 的 字典 一样 ,Map 是根据其键和值类型进行参数化的泛型。与 原生 Swift 集合 不同 Realm Map 是引用类型(类),而不是值类型(结构体)。

您可将 Map 声明为对象的属性:

class Dog: Object {
@Persisted var name = ""
@Persisted var currentCity = ""
// Map of city name -> favorite park in that city
@Persisted var favoriteParksByCity: Map<String, String>
}

Realm 不允许在映射键中使用 .$ 字符。您可以使用百分比编码和解码来存储包含这些不允许的任一字符的映射键。

// Percent encode . or $ characters to use them in map keys
let mapKey = "New York.Brooklyn"
let encodedMapKey = "New York%2EBrooklyn"

注意

@Persisted Map 属性声明默认值时,以下两种语法类型均有效:

  • @Persisted var value: Map<String, String>

  • @Persisted var value = Map<String, String>()

但是,第二种语法会导致性能大幅下降。这是因为 Map 是在创建父对象时创建的,而不是按需延迟创建的。

在版本10.51.0中进行了更改AnyRealmValue属性可以保存混合数据的列表或映射。

10.8.0 版本新增

AnyRealmValue 是一种 Realm 属性类型,它可保存不同数据类型。支持的 AnyRealmValue 数据类型包括:

  • Int

  • Float

  • double

  • Decimal128

  • ObjectID

  • UUID

  • bool

  • Date

  • 数据

  • 字符串

  • 名单

  • Map

  • 对象

AnyRealmValue 不能容纳MutableSet或嵌入式对象。

这种混合数据类型可索引的,但不能将其用主键。 由于null是允许值,因此您不能将AnyRealmValue声明为可选值。

class Dog: Object {
@Persisted var name = ""
@Persisted var currentCity = ""
@Persisted var companion: AnyRealmValue
}

在版本10.51.0及更高版本中, AnyRealmValue数据类型可以包含AnyRealmValue元素的集合(列表或映射,但不是设立)。 您可以使用混合集合对非结构化或可变数据进行建模。 有关更多信息,请参阅定义非结构化数据。

  • 您最多可以嵌套100级混合集合。

  • 您可以查询混合集合属性并注册变更监听器,就像查询普通集合一样。

  • 您可以查找并更新单个混合集合元素

  • 不能在混合集合中存储集合或嵌入式对象。

要在应用中使用混合集合,请在数据模型中定义AnyRealmValue类型属性。 然后,您可以像创建任何其他混合数据值一样创建列表或地图集合。

10.47.0 版本的新增功能

地理空间数据指定地球表面上的点和几何对象。

如果要持久保存地理空间数据,则必须符合 GeoJSON 规范。

要使用 Swift SDK 持久保存地理空间数据,请创建一个可以在数据模型中使用的 GeoJSON 兼容嵌入式类。

您的自定义嵌入式对象必须包含 GeoJSON 规范所需的两个字段:

  • String 类型的属性字段,它映射到一个值为 "Point"type 属性:@Persisted var type: String = "Point"

  • List<Double> 类型的字段,它映射到一个包含纬度/经度对的 coordinates 属性:@Persisted private var coordinates: List<Double>

class CustomGeoPoint: EmbeddedObject {
@Persisted private var type: String = "Point"
@Persisted private var coordinates: List<Double>
public var latitude: Double { return coordinates[1] }
public var longitude: Double { return coordinates[0] }
convenience init(_ latitude: Double, _ longitude: Double) {
self.init()
// Longitude comes first in the coordinates array of a GeoJson document
coordinates.append(objectsIn: [longitude, latitude])
}
}

版本 10.20.0 中的新增功能

您可以使用类型投影将不支持的类型保留为 Realm 中支持的类型。此举可让您使用 Realm 不支持的 Swift 类型,但可将其存储为 Realm 支持的类型。例如,您可将 URL 存储为 String,但可像 URL 一样从 Realm 中读取它并在应用程序中使用它。

要与 Realm 一起使用类型投影:

  1. 使用 Realm 的某一自定义类型协议将不支持的数据类型映射为 Realm 支持的类型

  2. 在 Realm 对象模型中将这些投影后的类型用作 @Persisted 属性

您可以使用某一 Realm 类型投影协议将不支持的数据类型映射为 Realm 支持的类型

Swift SDK 提供两种投影协议:

  • CustomPersistable

  • FailableCustomPersistable

当转换不可能失败时,请使用 CustomPersistable

当转换可能失败时,请使用 FailableCustomPersistable

// Extend a type as a CustomPersistable if if is impossible for
// conversion between the mapped type and the persisted type to fail.
extension CLLocationCoordinate2D: CustomPersistable {
// Define the storage object that is persisted to the database.
// The `PersistedType` must be a type that Realm supports.
// In this example, the PersistedType is an embedded object.
public typealias PersistedType = Location
// Construct an instance of the mapped type from the persisted type.
// When reading from the database, this converts the persisted type to the mapped type.
public init(persistedValue: PersistedType) {
self.init(latitude: persistedValue.latitude, longitude: persistedValue.longitude)
}
// Construct an instance of the persisted type from the mapped type.
// When writing to the database, this converts the mapped type to a persistable type.
public var persistableValue: PersistedType {
Location(value: [self.latitude, self.longitude])
}
}
// Extend a type as a FailableCustomPersistable if it is possible for
// conversion between the mapped type and the persisted type to fail.
// This returns nil on read if the underlying column contains nil or
// something that can't be converted to the specified type.
extension URL: FailableCustomPersistable {
// Define the storage object that is persisted to the database.
// The `PersistedType` must be a type that Realm supports.
public typealias PersistedType = String
// Construct an instance of the mapped type from the persisted type.
// When reading from the database, this converts the persisted type to the mapped type.
// This must be a failable initilizer when the conversion may fail.
public init?(persistedValue: String) { self.init(string: persistedValue) }
// Construct an instance of the persisted type from the mapped type.
// When writing to the database, this converts the mapped type to a persistable type.
public var persistableValue: String { self.absoluteString }
}

提示

这些协议均以 Swift 的内置 RawRepresentTable 作为蓝本。

PersistedType 可使用Swift SDK 支持的任何基元类型。 它也可以是嵌入式对象。

PersistedType 不能为可选项或集合。但是,您可将映射后的类型用作对象模型中的可选属性或集合属性。

extension URL: FailableCustomPersistable {
// The `PersistedType` cannot be an optional, so this is not a valid
// conformance to the FailableCustomPersistable protocol.
public typealias PersistedType = String?
...
}
class Club: Object {
@Persisted var id: ObjectId
@Persisted var name: String
// Although the `PersistedType` cannot be optional, you can use the
// custom-mapped type as an optional in your object model.
@Persisted var url: URL?
}

符合某一类型投影协议的类型可与 Swift SDK 版本 10.10.0 中引入的 @Persisted 属性声明语法一起使用。它不适用于 @objc dynamic 语法。

您可将投影类型用于:

  • 顶级类型

  • 类型的可选版本

  • 集合的类型

FailableCustomPersistable 用作属性时,请将其定义为可选属性。如果它为可选属性,FailableCustomPersistable 协议则会将无效值映射为 nil。当它为必需属性时,会将其强制展开。如果存在无法转换为投影类型的值,读取该属性则会引发因未展开而失败的异常。

class Club: Object {
@Persisted var id: ObjectId
@Persisted var name: String
// Since we declared the URL as a FailableCustomPersistable,
// it must be optional.
@Persisted var url: URL?
// Here, the `location` property maps to an embedded object.
// We can declare the property as required.
// If the underlying field contains nil, this becomes
// a default-constructed instance of CLLocationCoordinate
// with field values of `0`.
@Persisted var location: CLLocationCoordinate2D
}
public class Location: EmbeddedObject {
@Persisted var latitude: Double
@Persisted var longitude: Double
}

当模型包含投影后的类型时,既可使用持久类型来创建具有值的对象,也可使用投影后的类型为已初始化对象的字段属性分配该对象。

// Initialize objects and assign values
let club = Club(value: ["name": "American Kennel Club", "url": "https://akc.org"])
let club2 = Club()
club2.name = "Continental Kennel Club"
// When assigning the value to a type-projected property, type safety
// checks for the mapped type - not the persisted type.
club2.url = URL(string: "https://ckcusa.com/")!
club2.location = CLLocationCoordinate2D(latitude: 40.7509, longitude: 73.9777)

当您将类型声明为符合类型投影协议时,请指定应在 Realm 中保留的类型。例如,如果您将自定义类型 URL 映射为持久类型的 StringURL 属性则会在模式中显示为 String,且对该属性的动态访问也会作用于字符串。

模式不会直接表示映射后的类型。将属性从其持久化类型更改为映射后类型(反之亦然)无需进行迁移。

显示采用持久类型的字段类型的 Realm Studio 屏幕截图。

后退

关系

在此页面上