123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2015 Realm Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- ////////////////////////////////////////////////////////////////////////////
- import Foundation
- import Realm
- import Realm.Private
- #if !swift(>=4.1)
- fileprivate extension Sequence {
- func compactMap<T>(_ fn: (Self.Iterator.Element) throws -> T?) rethrows -> [T] {
- return try flatMap(fn)
- }
- }
- #endif
- extension Realm {
- /**
- A `Configuration` instance describes the different options used to create an instance of a Realm.
- `Configuration` instances are just plain Swift structs. Unlike `Realm`s and `Object`s, they can be freely shared
- between threads as long as you do not mutate them.
- Creating configuration values for class subsets (by setting the `objectClasses` property) can be expensive. Because
- of this, you will normally want to cache and reuse a single configuration value for each distinct configuration
- rather than creating a new value each time you open a Realm.
- */
- public struct Configuration {
- // MARK: Default Configuration
- /**
- The default `Configuration` used to create Realms when no configuration is explicitly specified (i.e.
- `Realm()`)
- */
- public static var defaultConfiguration: Configuration {
- get {
- return fromRLMRealmConfiguration(RLMRealmConfiguration.default())
- }
- set {
- RLMRealmConfiguration.setDefault(newValue.rlmConfiguration)
- }
- }
- // MARK: Initialization
- /**
- Creates a `Configuration` which can be used to create new `Realm` instances.
- - note: The `fileURL`, `inMemoryIdentifier`, and `syncConfiguration` parameters are mutually exclusive. Only
- set one of them, or none if you wish to use the default file URL.
- - parameter fileURL: The local URL to the Realm file.
- - parameter inMemoryIdentifier: A string used to identify a particular in-memory Realm.
- - parameter syncConfiguration: For Realms intended to sync with the Realm Object Server, a sync configuration.
- - parameter encryptionKey: An optional 64-byte key to use to encrypt the data.
- - parameter readOnly: Whether the Realm is read-only (must be true for read-only files).
- - parameter schemaVersion: The current schema version.
- - parameter migrationBlock: The block which migrates the Realm to the current version.
- - parameter deleteRealmIfMigrationNeeded: If `true`, recreate the Realm file with the provided
- schema if a migration is required.
- - parameter shouldCompactOnLaunch: A block called when opening a Realm for the first time during the
- life of a process to determine if it should be compacted before being
- returned to the user. It is passed the total file size (data + free space)
- and the total bytes used by data in the file.
- Return `true ` to indicate that an attempt to compact the file should be made.
- The compaction will be skipped if another process is accessing it.
- - parameter objectTypes: The subset of `Object` subclasses persisted in the Realm.
- */
- public init(fileURL: URL? = URL(fileURLWithPath: RLMRealmPathForFile("default.realm"), isDirectory: false),
- inMemoryIdentifier: String? = nil,
- syncConfiguration: SyncConfiguration? = nil,
- encryptionKey: Data? = nil,
- readOnly: Bool = false,
- schemaVersion: UInt64 = 0,
- migrationBlock: MigrationBlock? = nil,
- deleteRealmIfMigrationNeeded: Bool = false,
- shouldCompactOnLaunch: ((Int, Int) -> Bool)? = nil,
- objectTypes: [Object.Type]? = nil) {
- self.fileURL = fileURL
- if let inMemoryIdentifier = inMemoryIdentifier {
- self.inMemoryIdentifier = inMemoryIdentifier
- }
- if let syncConfiguration = syncConfiguration {
- self.syncConfiguration = syncConfiguration
- }
- self.encryptionKey = encryptionKey
- self.readOnly = readOnly
- self.schemaVersion = schemaVersion
- self.migrationBlock = migrationBlock
- self.deleteRealmIfMigrationNeeded = deleteRealmIfMigrationNeeded
- self.shouldCompactOnLaunch = shouldCompactOnLaunch
- self.objectTypes = objectTypes
- }
- // MARK: Configuration Properties
- /**
- A configuration value used to configure a Realm for synchronization with the Realm Object Server. Mutually
- exclusive with `inMemoryIdentifier`.
- */
- public var syncConfiguration: SyncConfiguration? {
- set {
- _inMemoryIdentifier = nil
- _syncConfiguration = newValue
- }
- get {
- return _syncConfiguration
- }
- }
- private var _syncConfiguration: SyncConfiguration?
- /// The local URL of the Realm file. Mutually exclusive with `inMemoryIdentifier`.
- public var fileURL: URL? {
- set {
- _inMemoryIdentifier = nil
- _path = newValue?.path
- }
- get {
- return _path.map { URL(fileURLWithPath: $0) }
- }
- }
- private var _path: String?
- /// A string used to identify a particular in-memory Realm. Mutually exclusive with `fileURL` and
- /// `syncConfiguration`.
- public var inMemoryIdentifier: String? {
- set {
- _path = nil
- _syncConfiguration = nil
- _inMemoryIdentifier = newValue
- }
- get {
- return _inMemoryIdentifier
- }
- }
- private var _inMemoryIdentifier: String?
- /// A 64-byte key to use to encrypt the data, or `nil` if encryption is not enabled.
- public var encryptionKey: Data?
- /**
- Whether to open the Realm in read-only mode.
- This is required to be able to open Realm files which are not writeable or are in a directory which is not
- writeable. This should only be used on files which will not be modified by anyone while they are open, and not
- just to get a read-only view of a file which may be written to by another thread or process. Opening in
- read-only mode requires disabling Realm's reader/writer coordination, so committing a write transaction from
- another process will result in crashes.
- */
- public var readOnly: Bool = false
- /// The current schema version.
- public var schemaVersion: UInt64 = 0
- /// The block which migrates the Realm to the current version.
- public var migrationBlock: MigrationBlock?
- /**
- Whether to recreate the Realm file with the provided schema if a migration is required. This is the case when
- the stored schema differs from the provided schema or the stored schema version differs from the version on
- this configuration. Setting this property to `true` deletes the file if a migration would otherwise be required
- or executed.
- - note: Setting this property to `true` doesn't disable file format migrations.
- */
- public var deleteRealmIfMigrationNeeded: Bool = false
- /**
- A block called when opening a Realm for the first time during the
- life of a process to determine if it should be compacted before being
- returned to the user. It is passed the total file size (data + free space)
- and the total bytes used by data in the file.
- Return `true ` to indicate that an attempt to compact the file should be made.
- The compaction will be skipped if another process is accessing it.
- */
- public var shouldCompactOnLaunch: ((Int, Int) -> Bool)?
- /// The classes managed by the Realm.
- public var objectTypes: [Object.Type]? {
- set {
- self.customSchema = newValue.map { RLMSchema(objectClasses: $0) }
- }
- get {
- return self.customSchema.map { $0.objectSchema.compactMap { $0.objectClass as? Object.Type } }
- }
- }
- /// A custom schema to use for the Realm.
- private var customSchema: RLMSchema?
- /// If `true`, disables automatic format upgrades when accessing the Realm.
- internal var disableFormatUpgrade: Bool = false
- // MARK: Private Methods
- internal var rlmConfiguration: RLMRealmConfiguration {
- let configuration = RLMRealmConfiguration()
- if let syncConfiguration = syncConfiguration {
- configuration.syncConfiguration = syncConfiguration.asConfig()
- }
- if let fileURL = fileURL {
- configuration.fileURL = fileURL
- } else if let inMemoryIdentifier = inMemoryIdentifier {
- configuration.inMemoryIdentifier = inMemoryIdentifier
- } else if syncConfiguration == nil {
- fatalError("A Realm Configuration must specify a path or an in-memory identifier.")
- }
- configuration.encryptionKey = self.encryptionKey
- configuration.readOnly = self.readOnly
- configuration.schemaVersion = self.schemaVersion
- configuration.migrationBlock = self.migrationBlock.map { accessorMigrationBlock($0) }
- configuration.deleteRealmIfMigrationNeeded = self.deleteRealmIfMigrationNeeded
- if let shouldCompactOnLaunch = self.shouldCompactOnLaunch {
- configuration.shouldCompactOnLaunch = ObjectiveCSupport.convert(object: shouldCompactOnLaunch)
- } else {
- configuration.shouldCompactOnLaunch = nil
- }
- configuration.setCustomSchemaWithoutCopying(self.customSchema)
- configuration.disableFormatUpgrade = self.disableFormatUpgrade
- return configuration
- }
- internal static func fromRLMRealmConfiguration(_ rlmConfiguration: RLMRealmConfiguration) -> Configuration {
- var configuration = Configuration()
- configuration._path = rlmConfiguration.fileURL?.path
- configuration._inMemoryIdentifier = rlmConfiguration.inMemoryIdentifier
- if let objcSyncConfig = rlmConfiguration.syncConfiguration {
- configuration._syncConfiguration = SyncConfiguration(config: objcSyncConfig)
- } else {
- configuration._syncConfiguration = nil
- }
- configuration.encryptionKey = rlmConfiguration.encryptionKey
- configuration.readOnly = rlmConfiguration.readOnly
- configuration.schemaVersion = rlmConfiguration.schemaVersion
- configuration.migrationBlock = rlmConfiguration.migrationBlock.map { rlmMigration in
- return { migration, schemaVersion in
- rlmMigration(migration.rlmMigration, schemaVersion)
- }
- }
- configuration.deleteRealmIfMigrationNeeded = rlmConfiguration.deleteRealmIfMigrationNeeded
- configuration.shouldCompactOnLaunch = rlmConfiguration.shouldCompactOnLaunch.map(ObjectiveCSupport.convert)
- configuration.customSchema = rlmConfiguration.customSchema
- configuration.disableFormatUpgrade = rlmConfiguration.disableFormatUpgrade
- return configuration
- }
- }
- }
- // MARK: CustomStringConvertible
- extension Realm.Configuration: CustomStringConvertible {
- /// A human-readable description of the configuration value.
- public var description: String {
- return gsub(pattern: "\\ARLMRealmConfiguration",
- template: "Realm.Configuration",
- string: rlmConfiguration.description) ?? ""
- }
- }
|