added iOS source code
[wl-app.git] / iOS / Pods / RealmSwift / RealmSwift / RealmConfiguration.swift
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2015 Realm Inc.
4 //
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
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 import Foundation
20 import Realm
21 import Realm.Private
22
23 extension Realm {
24     /**
25      A `Configuration` instance describes the different options used to create an instance of a Realm.
26
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.
29
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.
33      */
34     public struct Configuration {
35
36         // MARK: Default Configuration
37
38         /**
39          The default `Configuration` used to create Realms when no configuration is explicitly specified (i.e.
40          `Realm()`)
41          */
42         public static var defaultConfiguration: Configuration {
43             get {
44                 return fromRLMRealmConfiguration(RLMRealmConfiguration.default())
45             }
46             set {
47                 RLMRealmConfiguration.setDefault(newValue.rlmConfiguration)
48             }
49         }
50
51         // MARK: Initialization
52
53         /**
54          Creates a `Configuration` which can be used to create new `Realm` instances.
55
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.
58
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.
72
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.
76         */
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
90                 }
91                 if let syncConfiguration = syncConfiguration {
92                     self.syncConfiguration = syncConfiguration
93                 }
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
101         }
102
103         // MARK: Configuration Properties
104
105         /**
106          A configuration value used to configure a Realm for synchronization with the Realm Object Server. Mutually
107          exclusive with `inMemoryIdentifier` and `fileURL`.
108          */
109         public var syncConfiguration: SyncConfiguration? {
110             set {
111                 _path = nil
112                 _inMemoryIdentifier = nil
113                 _syncConfiguration = newValue
114             }
115             get {
116                 return _syncConfiguration
117             }
118         }
119
120         private var _syncConfiguration: SyncConfiguration?
121
122         /// The local URL of the Realm file. Mutually exclusive with `inMemoryIdentifier` and `syncConfiguration`.
123         public var fileURL: URL? {
124             set {
125                 _inMemoryIdentifier = nil
126                 _syncConfiguration = nil
127                 _path = newValue?.path
128             }
129             get {
130                 return _path.map { URL(fileURLWithPath: $0) }
131             }
132         }
133
134         private var _path: String?
135
136         /// A string used to identify a particular in-memory Realm. Mutually exclusive with `fileURL` and
137         /// `syncConfiguration`.
138         public var inMemoryIdentifier: String? {
139             set {
140                 _path = nil
141                 _syncConfiguration = nil
142                 _inMemoryIdentifier = newValue
143             }
144             get {
145                 return _inMemoryIdentifier
146             }
147         }
148
149         private var _inMemoryIdentifier: String?
150
151         /// A 64-byte key to use to encrypt the data, or `nil` if encryption is not enabled.
152         public var encryptionKey: Data?
153
154         /**
155          Whether to open the Realm in read-only mode.
156
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.
162          */
163         public var readOnly: Bool = false
164
165         /// The current schema version.
166         public var schemaVersion: UInt64 = 0
167
168         /// The block which migrates the Realm to the current version.
169         public var migrationBlock: MigrationBlock?
170
171         /**
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
175          or executed.
176
177          - note: Setting this property to `true` doesn't disable file format migrations.
178          */
179         public var deleteRealmIfMigrationNeeded: Bool = false
180
181         /**
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.
186
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.
189          */
190         public var shouldCompactOnLaunch: ((Int, Int) -> Bool)?
191
192         /// The classes managed by the Realm.
193         public var objectTypes: [Object.Type]? {
194             set {
195                 self.customSchema = newValue.map { RLMSchema(objectClasses: $0) }
196             }
197             get {
198                 return self.customSchema.map { $0.objectSchema.map { $0.objectClass as! Object.Type } }
199             }
200         }
201
202         /// A custom schema to use for the Realm.
203         private var customSchema: RLMSchema?
204
205         /// If `true`, disables automatic format upgrades when accessing the Realm.
206         internal var disableFormatUpgrade: Bool = false
207
208         // MARK: Private Methods
209
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()
218             } else {
219                 fatalError("A Realm Configuration must specify a path or an in-memory identifier.")
220             }
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)
228             } else {
229                 configuration.shouldCompactOnLaunch = nil
230             }
231             configuration.setCustomSchemaWithoutCopying(self.customSchema)
232             configuration.disableFormatUpgrade = self.disableFormatUpgrade
233             return configuration
234         }
235
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)
242             } else {
243                 configuration._syncConfiguration = nil
244             }
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)
251                 }
252             }
253             configuration.deleteRealmIfMigrationNeeded = rlmConfiguration.deleteRealmIfMigrationNeeded
254             configuration.shouldCompactOnLaunch = rlmConfiguration.shouldCompactOnLaunch.map(ObjectiveCSupport.convert)
255             configuration.customSchema = rlmConfiguration.customSchema
256             configuration.disableFormatUpgrade = rlmConfiguration.disableFormatUpgrade
257             return configuration
258         }
259     }
260 }
261
262 // MARK: CustomStringConvertible
263
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) ?? ""
270     }
271 }