1 ////////////////////////////////////////////////////////////////////////////
3 // Copyright 2015 Realm Inc.
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 ////////////////////////////////////////////////////////////////////////////
25 A `Configuration` instance describes the different options used to create an instance of a Realm.
27 `Configuration` instances are just plain Swift structs. Unlike `Realm`s and `Object`s, they can be freely shared
28 between threads as long as you do not mutate them.
30 Creating configuration values for class subsets (by setting the `objectClasses` property) can be expensive. Because
31 of this, you will normally want to cache and reuse a single configuration value for each distinct configuration
32 rather than creating a new value each time you open a Realm.
34 public struct Configuration {
36 // MARK: Default Configuration
39 The default `Configuration` used to create Realms when no configuration is explicitly specified (i.e.
42 public static var defaultConfiguration: Configuration {
44 return fromRLMRealmConfiguration(RLMRealmConfiguration.default())
47 RLMRealmConfiguration.setDefault(newValue.rlmConfiguration)
51 // MARK: Initialization
54 Creates a `Configuration` which can be used to create new `Realm` instances.
56 - note: The `fileURL`, `inMemoryIdentifier`, and `syncConfiguration` parameters are mutually exclusive. Only
57 set one of them, or none if you wish to use the default file URL.
59 - parameter fileURL: The local URL to the Realm file.
60 - parameter inMemoryIdentifier: A string used to identify a particular in-memory Realm.
61 - parameter syncConfiguration: For Realms intended to sync with the Realm Object Server, a sync configuration.
62 - parameter encryptionKey: An optional 64-byte key to use to encrypt the data.
63 - parameter readOnly: Whether the Realm is read-only (must be true for read-only files).
64 - parameter schemaVersion: The current schema version.
65 - parameter migrationBlock: The block which migrates the Realm to the current version.
66 - parameter deleteRealmIfMigrationNeeded: If `true`, recreate the Realm file with the provided
67 schema if a migration is required.
68 - parameter shouldCompactOnLaunch: A block called when opening a Realm for the first time during the
69 life of a process to determine if it should be compacted before being
70 returned to the user. It is passed the total file size (data + free space)
71 and the total bytes used by data in the file.
73 Return `true ` to indicate that an attempt to compact the file should be made.
74 The compaction will be skipped if another process is accessing it.
75 - parameter objectTypes: The subset of `Object` subclasses persisted in the Realm.
77 public init(fileURL: URL? = URL(fileURLWithPath: RLMRealmPathForFile("default.realm"), isDirectory: false),
78 inMemoryIdentifier: String? = nil,
79 syncConfiguration: SyncConfiguration? = nil,
80 encryptionKey: Data? = nil,
81 readOnly: Bool = false,
82 schemaVersion: UInt64 = 0,
83 migrationBlock: MigrationBlock? = nil,
84 deleteRealmIfMigrationNeeded: Bool = false,
85 shouldCompactOnLaunch: ((Int, Int) -> Bool)? = nil,
86 objectTypes: [Object.Type]? = nil) {
87 self.fileURL = fileURL
88 if let inMemoryIdentifier = inMemoryIdentifier {
89 self.inMemoryIdentifier = inMemoryIdentifier
91 if let syncConfiguration = syncConfiguration {
92 self.syncConfiguration = syncConfiguration
94 self.encryptionKey = encryptionKey
95 self.readOnly = readOnly
96 self.schemaVersion = schemaVersion
97 self.migrationBlock = migrationBlock
98 self.deleteRealmIfMigrationNeeded = deleteRealmIfMigrationNeeded
99 self.shouldCompactOnLaunch = shouldCompactOnLaunch
100 self.objectTypes = objectTypes
103 // MARK: Configuration Properties
106 A configuration value used to configure a Realm for synchronization with the Realm Object Server. Mutually
107 exclusive with `inMemoryIdentifier` and `fileURL`.
109 public var syncConfiguration: SyncConfiguration? {
112 _inMemoryIdentifier = nil
113 _syncConfiguration = newValue
116 return _syncConfiguration
120 private var _syncConfiguration: SyncConfiguration?
122 /// The local URL of the Realm file. Mutually exclusive with `inMemoryIdentifier` and `syncConfiguration`.
123 public var fileURL: URL? {
125 _inMemoryIdentifier = nil
126 _syncConfiguration = nil
127 _path = newValue?.path
130 return _path.map { URL(fileURLWithPath: $0) }
134 private var _path: String?
136 /// A string used to identify a particular in-memory Realm. Mutually exclusive with `fileURL` and
137 /// `syncConfiguration`.
138 public var inMemoryIdentifier: String? {
141 _syncConfiguration = nil
142 _inMemoryIdentifier = newValue
145 return _inMemoryIdentifier
149 private var _inMemoryIdentifier: String?
151 /// A 64-byte key to use to encrypt the data, or `nil` if encryption is not enabled.
152 public var encryptionKey: Data?
155 Whether to open the Realm in read-only mode.
157 This is required to be able to open Realm files which are not writeable or are in a directory which is not
158 writeable. This should only be used on files which will not be modified by anyone while they are open, and not
159 just to get a read-only view of a file which may be written to by another thread or process. Opening in
160 read-only mode requires disabling Realm's reader/writer coordination, so committing a write transaction from
161 another process will result in crashes.
163 public var readOnly: Bool = false
165 /// The current schema version.
166 public var schemaVersion: UInt64 = 0
168 /// The block which migrates the Realm to the current version.
169 public var migrationBlock: MigrationBlock?
172 Whether to recreate the Realm file with the provided schema if a migration is required. This is the case when
173 the stored schema differs from the provided schema or the stored schema version differs from the version on
174 this configuration. Setting this property to `true` deletes the file if a migration would otherwise be required
177 - note: Setting this property to `true` doesn't disable file format migrations.
179 public var deleteRealmIfMigrationNeeded: Bool = false
182 A block called when opening a Realm for the first time during the
183 life of a process to determine if it should be compacted before being
184 returned to the user. It is passed the total file size (data + free space)
185 and the total bytes used by data in the file.
187 Return `true ` to indicate that an attempt to compact the file should be made.
188 The compaction will be skipped if another process is accessing it.
190 public var shouldCompactOnLaunch: ((Int, Int) -> Bool)?
192 /// The classes managed by the Realm.
193 public var objectTypes: [Object.Type]? {
195 self.customSchema = newValue.map { RLMSchema(objectClasses: $0) }
198 return self.customSchema.map { $0.objectSchema.map { $0.objectClass as! Object.Type } }
202 /// A custom schema to use for the Realm.
203 private var customSchema: RLMSchema?
205 /// If `true`, disables automatic format upgrades when accessing the Realm.
206 internal var disableFormatUpgrade: Bool = false
208 // MARK: Private Methods
210 internal var rlmConfiguration: RLMRealmConfiguration {
211 let configuration = RLMRealmConfiguration()
212 if let fileURL = fileURL {
213 configuration.fileURL = fileURL
214 } else if let inMemoryIdentifier = inMemoryIdentifier {
215 configuration.inMemoryIdentifier = inMemoryIdentifier
216 } else if let syncConfiguration = syncConfiguration {
217 configuration.syncConfiguration = syncConfiguration.asConfig()
219 fatalError("A Realm Configuration must specify a path or an in-memory identifier.")
221 configuration.encryptionKey = self.encryptionKey
222 configuration.readOnly = self.readOnly
223 configuration.schemaVersion = self.schemaVersion
224 configuration.migrationBlock = self.migrationBlock.map { accessorMigrationBlock($0) }
225 configuration.deleteRealmIfMigrationNeeded = self.deleteRealmIfMigrationNeeded
226 if let shouldCompactOnLaunch = self.shouldCompactOnLaunch {
227 configuration.shouldCompactOnLaunch = ObjectiveCSupport.convert(object: shouldCompactOnLaunch)
229 configuration.shouldCompactOnLaunch = nil
231 configuration.setCustomSchemaWithoutCopying(self.customSchema)
232 configuration.disableFormatUpgrade = self.disableFormatUpgrade
236 internal static func fromRLMRealmConfiguration(_ rlmConfiguration: RLMRealmConfiguration) -> Configuration {
237 var configuration = Configuration()
238 configuration._path = rlmConfiguration.fileURL?.path
239 configuration._inMemoryIdentifier = rlmConfiguration.inMemoryIdentifier
240 if let objcSyncConfig = rlmConfiguration.syncConfiguration {
241 configuration._syncConfiguration = SyncConfiguration(config: objcSyncConfig)
243 configuration._syncConfiguration = nil
245 configuration.encryptionKey = rlmConfiguration.encryptionKey
246 configuration.readOnly = rlmConfiguration.readOnly
247 configuration.schemaVersion = rlmConfiguration.schemaVersion
248 configuration.migrationBlock = rlmConfiguration.migrationBlock.map { rlmMigration in
249 return { migration, schemaVersion in
250 rlmMigration(migration.rlmMigration, schemaVersion)
253 configuration.deleteRealmIfMigrationNeeded = rlmConfiguration.deleteRealmIfMigrationNeeded
254 configuration.shouldCompactOnLaunch = rlmConfiguration.shouldCompactOnLaunch.map(ObjectiveCSupport.convert)
255 configuration.customSchema = rlmConfiguration.customSchema
256 configuration.disableFormatUpgrade = rlmConfiguration.disableFormatUpgrade
262 // MARK: CustomStringConvertible
264 extension Realm.Configuration: CustomStringConvertible {
265 /// A human-readable description of the configuration value.
266 public var description: String {
267 return gsub(pattern: "\\ARLMRealmConfiguration",
268 template: "Realm.Configuration",
269 string: rlmConfiguration.description) ?? ""