added iOS source code
[wl-app.git] / iOS / Pods / RealmSwift / RealmSwift / Realm.swift
diff --git a/iOS/Pods/RealmSwift/RealmSwift/Realm.swift b/iOS/Pods/RealmSwift/RealmSwift/Realm.swift
new file mode 100644 (file)
index 0000000..def1432
--- /dev/null
@@ -0,0 +1,713 @@
+////////////////////////////////////////////////////////////////////////////
+//
+// Copyright 2014 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
+
+/**
+ A `Realm` instance (also referred to as "a Realm") represents a Realm database.
+
+ Realms can either be stored on disk (see `init(path:)`) or in memory (see `Configuration`).
+
+ `Realm` instances are cached internally, and constructing equivalent `Realm` objects (for example, by using the same
+ path or identifier) produces limited overhead.
+
+ If you specifically want to ensure a `Realm` instance is destroyed (for example, if you wish to open a Realm, check
+ some property, and then possibly delete the Realm file and re-open it), place the code which uses the Realm within an
+ `autoreleasepool {}` and ensure you have no other strong references to it.
+
+ - warning: `Realm` instances are not thread safe and cannot be shared across threads or dispatch queues. You must
+ construct a new instance for each thread in which a Realm will be accessed. For dispatch queues, this means
+ that you must construct a new instance in each block which is dispatched, as a queue is not guaranteed to
+ run all of its blocks on the same thread.
+ */
+public final class Realm {
+
+    // MARK: Properties
+
+    /// The `Schema` used by the Realm.
+    public var schema: Schema { return Schema(rlmRealm.schema) }
+
+    /// The `Configuration` value that was used to create the `Realm` instance.
+    public var configuration: Configuration { return Configuration.fromRLMRealmConfiguration(rlmRealm.configuration) }
+
+    /// Indicates if the Realm contains any objects.
+    public var isEmpty: Bool { return rlmRealm.isEmpty }
+
+    // MARK: Initializers
+
+    /**
+     Obtains an instance of the default Realm.
+
+     The default Realm is persisted as *default.realm* under the *Documents* directory of your Application on iOS, and
+     in your application's *Application Support* directory on OS X.
+
+     The default Realm is created using the default `Configuration`, which can be changed by setting the
+     `Realm.Configuration.defaultConfiguration` property to a new value.
+
+     - throws: An `NSError` if the Realm could not be initialized.
+     */
+    public convenience init() throws {
+        let rlmRealm = try RLMRealm(configuration: RLMRealmConfiguration.default())
+        self.init(rlmRealm)
+    }
+
+    /**
+     Obtains a `Realm` instance with the given configuration.
+
+     - parameter configuration: A configuration value to use when creating the Realm.
+
+     - throws: An `NSError` if the Realm could not be initialized.
+     */
+    public convenience init(configuration: Configuration) throws {
+        let rlmRealm = try RLMRealm(configuration: configuration.rlmConfiguration)
+        self.init(rlmRealm)
+    }
+
+    /**
+     Obtains a `Realm` instance persisted at a specified file URL.
+
+     - parameter fileURL: The local URL of the file the Realm should be saved at.
+
+     - throws: An `NSError` if the Realm could not be initialized.
+     */
+    public convenience init(fileURL: URL) throws {
+        var configuration = Configuration.defaultConfiguration
+        configuration.fileURL = fileURL
+        try self.init(configuration: configuration)
+    }
+
+    // MARK: Async
+
+    /**
+     Asynchronously open a Realm and deliver it to a block on the given queue.
+
+     Opening a Realm asynchronously will perform all work needed to get the Realm to
+     a usable state (such as running potentially time-consuming migrations) on a
+     background thread before dispatching to the given queue. In addition,
+     synchronized Realms wait for all remote content available at the time the
+     operation began to be downloaded and available locally.
+
+     - parameter configuration: A configuration object to use when opening the Realm.
+     - parameter callbackQueue: The dispatch queue on which the callback should be run.
+     - parameter callback:      A callback block. If the Realm was successfully opened, an
+                                it will be passed in as an argument.
+                                Otherwise, a `Swift.Error` describing what went wrong will be
+                                passed to the block instead.
+
+     - note: The returned Realm is confined to the thread on which it was created.
+             Because GCD does not guarantee that queues will always use the same
+             thread, accessing the returned Realm outside the callback block (even if
+             accessed from `callbackQueue`) is unsafe.
+     */
+    public static func asyncOpen(configuration: Realm.Configuration = .defaultConfiguration,
+                                 callbackQueue: DispatchQueue = .main,
+                                 callback: @escaping (Realm?, Swift.Error?) -> Void) {
+        RLMRealm.asyncOpen(with: configuration.rlmConfiguration, callbackQueue: callbackQueue) { rlmRealm, error in
+            callback(rlmRealm.flatMap(Realm.init), error)
+        }
+    }
+
+    // MARK: Transactions
+
+    /**
+     Performs actions contained within the given block inside a write transaction.
+
+     If the block throws an error, the transaction will be canceled and any
+     changes made before the error will be rolled back.
+
+     Only one write transaction can be open at a time for each Realm file. Write
+     transactions cannot be nested, and trying to begin a write transaction on a
+     Realm which is already in a write transaction will throw an exception.
+     Calls to `write` from `Realm` instances for the same Realm file in other
+     threads or other processes will block until the current write transaction
+     completes or is cancelled.
+
+     Before beginning the write transaction, `write` updates the `Realm`
+     instance to the latest Realm version, as if `refresh()` had been called,
+     and generates notifications if applicable. This has no effect if the Realm
+     was already up to date.
+
+     - parameter block: The block containing actions to perform.
+
+     - throws: An `NSError` if the transaction could not be completed successfully.
+               If `block` throws, the function throws the propagated `ErrorType` instead.
+     */
+    public func write(_ block: (() throws -> Void)) throws {
+        beginWrite()
+        do {
+            try block()
+        } catch let error {
+            if isInWriteTransaction { cancelWrite() }
+            throw error
+        }
+        if isInWriteTransaction { try commitWrite() }
+    }
+
+    /**
+     Begins a write transaction on the Realm.
+
+     Only one write transaction can be open at a time for each Realm file. Write
+     transactions cannot be nested, and trying to begin a write transaction on a
+     Realm which is already in a write transaction will throw an exception.
+     Calls to `beginWrite` from `Realm` instances for the same Realm file in
+     other threads or other processes will block until the current write
+     transaction completes or is cancelled.
+
+     Before beginning the write transaction, `beginWrite` updates the `Realm`
+     instance to the latest Realm version, as if `refresh()` had been called,
+     and generates notifications if applicable. This has no effect if the Realm
+     was already up to date.
+
+     It is rarely a good idea to have write transactions span multiple cycles of
+     the run loop, but if you do wish to do so you will need to ensure that the
+     Realm participating in the write transaction is kept alive until the write
+     transaction is committed.
+     */
+    public func beginWrite() {
+        rlmRealm.beginWriteTransaction()
+    }
+
+    /**
+     Commits all write operations in the current write transaction, and ends
+     the transaction.
+
+     After saving the changes and completing the write transaction, all
+     notification blocks registered on this specific `Realm` instance are called
+     synchronously. Notification blocks for `Realm` instances on other threads
+     and blocks registered for any Realm collection (including those on the
+     current thread) are scheduled to be called synchronously.
+
+     You can skip notifiying specific notification blocks about the changes made
+     in this write transaction by passing in their associated notification
+     tokens. This is primarily useful when the write transaction is saving
+     changes already made in the UI and you do not want to have the notification
+     block attempt to re-apply the same changes.
+
+     The tokens passed to this function must be for notifications for this Realm
+     which were added on the same thread as the write transaction is being
+     performed on. Notifications for different threads cannot be skipped using
+     this method.
+
+     - warning: This method may only be called during a write transaction.
+
+     - throws: An `NSError` if the transaction could not be written due to
+               running out of disk space or other i/o errors.
+     */
+    public func commitWrite(withoutNotifying tokens: [NotificationToken] = []) throws {
+        try rlmRealm.commitWriteTransactionWithoutNotifying(tokens)
+    }
+
+    /**
+     Reverts all writes made in the current write transaction and ends the transaction.
+
+     This rolls back all objects in the Realm to the state they were in at the
+     beginning of the write transaction, and then ends the transaction.
+
+     This restores the data for deleted objects, but does not revive invalidated
+     object instances. Any `Object`s which were added to the Realm will be
+     invalidated rather than becoming unmanaged.
+
+     Given the following code:
+
+     ```swift
+     let oldObject = objects(ObjectType).first!
+     let newObject = ObjectType()
+
+     realm.beginWrite()
+     realm.add(newObject)
+     realm.delete(oldObject)
+     realm.cancelWrite()
+     ```
+
+     Both `oldObject` and `newObject` will return `true` for `isInvalidated`,
+     but re-running the query which provided `oldObject` will once again return
+     the valid object.
+
+     KVO observers on any objects which were modified during the transaction
+     will be notified about the change back to their initial values, but no
+     other notifcations are produced by a cancelled write transaction.
+
+     - warning: This method may only be called during a write transaction.
+     */
+    public func cancelWrite() {
+        rlmRealm.cancelWriteTransaction()
+    }
+
+    /**
+     Indicates whether the Realm is currently in a write transaction.
+
+     - warning:  Do not simply check this property and then start a write transaction whenever an object needs to be
+                 created, updated, or removed. Doing so might cause a large number of write transactions to be created,
+                 degrading performance. Instead, always prefer performing multiple updates during a single transaction.
+     */
+    public var isInWriteTransaction: Bool {
+        return rlmRealm.inWriteTransaction
+    }
+
+    // MARK: Adding and Creating objects
+
+    /**
+     Adds or updates an existing object into the Realm.
+
+     Only pass `true` to `update` if the object has a primary key. If no object exists in the Realm with the same
+     primary key value, the object is inserted. Otherwise, the existing object is updated with any changed values.
+
+     When added, all child relationships referenced by this object will also be added to the Realm if they are not
+     already in it. If the object or any related objects are already being managed by a different Realm an error will be
+     thrown. Instead, use one of the `create` functions to insert a copy of a managed object into a different Realm.
+
+     The object to be added must be valid and cannot have been previously deleted from a Realm (i.e. `isInvalidated`
+     must be `false`).
+
+     - parameter object: The object to be added to this Realm.
+     - parameter update: If `true`, the Realm will try to find an existing copy of the object (with the same primary
+                         key), and update it. Otherwise, the object will be added.
+     */
+    public func add(_ object: Object, update: Bool = false) {
+        if update && object.objectSchema.primaryKeyProperty == nil {
+            throwRealmException("'\(object.objectSchema.className)' does not have a primary key and can not be updated")
+        }
+        RLMAddObjectToRealm(object, rlmRealm, update)
+    }
+
+    /**
+     Adds or updates all the objects in a collection into the Realm.
+
+     - see: `add(_:update:)`
+
+     - warning: This method may only be called during a write transaction.
+
+     - parameter objects: A sequence which contains objects to be added to the Realm.
+     - parameter update: If `true`, objects that are already in the Realm will be updated instead of added anew.
+     */
+    public func add<S: Sequence>(_ objects: S, update: Bool = false) where S.Iterator.Element: Object {
+        for obj in objects {
+            add(obj, update: update)
+        }
+    }
+
+    /**
+     Creates or updates a Realm object with a given value, adding it to the Realm and returning it.
+
+     You may only pass `true` to `update` if the object has a primary key. If no object exists
+     in the Realm with the same primary key value, the object is inserted. Otherwise, the
+     existing object is updated with any changed values.
+
+     The `value` argument can be a Realm object, a key-value coding compliant object, an array
+     or dictionary returned from the methods in `NSJSONSerialization`, or an `Array` containing
+     one element for each managed property. Do not pass in a `LinkingObjects` instance, either
+     by itself or as a member of a collection.
+
+     If the object is being created, all required properties that were not defined with default
+     values must be given initial values through the `value` argument. Otherwise, an Objective-C
+     exception will be thrown.
+
+     If the object is being updated, all properties defined in its schema will be set by copying
+     from `value` using key-value coding. If the `value` argument does not respond to `value(forKey:)`
+     for a given property name (or getter name, if defined), that value will remain untouched.
+     Nullable properties on the object can be set to nil by using `NSNull` as the updated value,
+     or (if you are passing in an instance of an `Object` subclass) setting the corresponding
+     property on `value` to nil.
+
+     If the `value` argument is an array, all properties must be present, valid and in the same
+     order as the properties defined in the model.
+
+     - warning: This method may only be called during a write transaction.
+
+     - parameter type:   The type of the object to create.
+     - parameter value:  The value used to populate the object.
+     - parameter update: If `true`, the Realm will try to find an existing copy of the object (with the same primary
+                         key), and update it. Otherwise, the object will be added.
+
+     - returns: The newly created object.
+     */
+    @discardableResult
+    public func create<T: Object>(_ type: T.Type, value: Any = [:], update: Bool = false) -> T {
+        let typeName = (type as Object.Type).className()
+        if update && schema[typeName]?.primaryKeyProperty == nil {
+            throwRealmException("'\(typeName)' does not have a primary key and can not be updated")
+        }
+        return unsafeDowncast(RLMCreateObjectInRealmWithValue(rlmRealm, typeName, value, update), to: T.self)
+    }
+
+    /**
+     This method is useful only in specialized circumstances, for example, when building
+     components that integrate with Realm. If you are simply building an app on Realm, it is
+     recommended to use the typed method `create(_:value:update:)`.
+
+     Creates or updates an object with the given class name and adds it to the `Realm`, populating
+     the object with the given value.
+
+     You may only pass `true` to `update` if the object has a primary key. If no object exists
+     in the Realm with the same primary key value, the object is inserted. Otherwise, the
+     existing object is updated with any changed values.
+
+     The `value` argument can be a Realm object, a key-value coding compliant object, an array
+     or dictionary returned from the methods in `NSJSONSerialization`, or an `Array` containing
+     one element for each managed property. Do not pass in a `LinkingObjects` instance, either
+     by itself or as a member of a collection.
+
+     If the object is being created, all required properties that were not defined with default
+     values must be given initial values through the `value` argument. Otherwise, an Objective-C
+     exception will be thrown.
+
+     If the object is being updated, all properties defined in its schema will be set by copying
+     from `value` using key-value coding. If the `value` argument does not respond to `value(forKey:)`
+     for a given property name (or getter name, if defined), that value will remain untouched.
+     Nullable properties on the object can be set to nil by using `NSNull` as the updated value.
+
+     If the `value` argument is an array, all properties must be present, valid and in the same
+     order as the properties defined in the model.
+
+     - warning: This method can only be called during a write transaction.
+
+     - parameter className:  The class name of the object to create.
+     - parameter value:      The value used to populate the object.
+     - parameter update:     If true will try to update existing objects with the same primary key.
+
+     - returns: The created object.
+
+     :nodoc:
+     */
+    @discardableResult
+    public func dynamicCreate(_ typeName: String, value: Any = [:], update: Bool = false) -> DynamicObject {
+        if update && schema[typeName]?.primaryKeyProperty == nil {
+            throwRealmException("'\(typeName)' does not have a primary key and can not be updated")
+        }
+        return noWarnUnsafeBitCast(RLMCreateObjectInRealmWithValue(rlmRealm, typeName, value, update),
+                                   to: DynamicObject.self)
+    }
+
+    // MARK: Deleting objects
+
+    /**
+     Deletes an object from the Realm. Once the object is deleted it is considered invalidated.
+
+     - warning: This method may only be called during a write transaction.
+
+     - parameter object: The object to be deleted.
+     */
+    public func delete(_ object: Object) {
+        RLMDeleteObjectFromRealm(object, rlmRealm)
+    }
+
+    /**
+     Deletes zero or more objects from the Realm.
+
+     Do not pass in a slice to a `Results` or any other auto-updating Realm collection
+     type (for example, the type returned by the Swift `suffix(_:)` standard library
+     method). Instead, make a copy of the objects to delete using `Array()`, and pass
+     that instead. Directly passing in a view into an auto-updating collection may
+     result in 'index out of bounds' exceptions being thrown.
+
+     - warning: This method may only be called during a write transaction.
+
+     - parameter objects:   The objects to be deleted. This can be a `List<Object>`,
+                            `Results<Object>`, or any other Swift `Sequence` whose
+                            elements are `Object`s (subject to the caveats above).
+     */
+    public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: Object {
+        for obj in objects {
+            delete(obj)
+        }
+    }
+
+    /**
+     Deletes zero or more objects from the Realm.
+
+     - warning: This method may only be called during a write transaction.
+
+     - parameter objects: A list of objects to delete.
+
+     :nodoc:
+     */
+    public func delete<Element: Object>(_ objects: List<Element>) {
+        rlmRealm.deleteObjects(objects._rlmArray)
+    }
+
+    /**
+     Deletes zero or more objects from the Realm.
+
+     - warning: This method may only be called during a write transaction.
+
+     - parameter objects: A `Results` containing the objects to be deleted.
+
+     :nodoc:
+     */
+    public func delete<Element: Object>(_ objects: Results<Element>) {
+        rlmRealm.deleteObjects(objects.rlmResults)
+    }
+
+    /**
+     Deletes all objects from the Realm.
+
+     - warning: This method may only be called during a write transaction.
+     */
+    public func deleteAll() {
+        RLMDeleteAllObjectsFromRealm(rlmRealm)
+    }
+
+    // MARK: Object Retrieval
+
+    /**
+     Returns all objects of the given type stored in the Realm.
+
+     - parameter type: The type of the objects to be returned.
+
+     - returns: A `Results` containing the objects.
+     */
+    public func objects<Element: Object>(_ type: Element.Type) -> Results<Element> {
+        return Results(RLMGetObjects(rlmRealm, type.className(), nil))
+    }
+
+    /**
+     This method is useful only in specialized circumstances, for example, when building
+     components that integrate with Realm. If you are simply building an app on Realm, it is
+     recommended to use the typed method `objects(type:)`.
+
+     Returns all objects for a given class name in the Realm.
+
+     - parameter typeName: The class name of the objects to be returned.
+     - returns: All objects for the given class name as dynamic objects
+
+     :nodoc:
+     */
+    public func dynamicObjects(_ typeName: String) -> Results<DynamicObject> {
+        return Results<DynamicObject>(RLMGetObjects(rlmRealm, typeName, nil))
+    }
+
+    /**
+     Retrieves the single instance of a given object type with the given primary key from the Realm.
+
+     This method requires that `primaryKey()` be overridden on the given object class.
+
+     - see: `Object.primaryKey()`
+
+     - parameter type: The type of the object to be returned.
+     - parameter key:  The primary key of the desired object.
+
+     - returns: An object of type `type`, or `nil` if no instance with the given primary key exists.
+     */
+    public func object<Element: Object, KeyType>(ofType type: Element.Type, forPrimaryKey key: KeyType) -> Element? {
+        return unsafeBitCast(RLMGetObject(rlmRealm, (type as Object.Type).className(),
+                                          dynamicBridgeCast(fromSwift: key)) as! RLMObjectBase?,
+                             to: Optional<Element>.self)
+    }
+
+    /**
+     This method is useful only in specialized circumstances, for example, when building
+     components that integrate with Realm. If you are simply building an app on Realm, it is
+     recommended to use the typed method `objectForPrimaryKey(_:key:)`.
+
+     Get a dynamic object with the given class name and primary key.
+
+     Returns `nil` if no object exists with the given class name and primary key.
+
+     This method requires that `primaryKey()` be overridden on the given subclass.
+
+     - see: Object.primaryKey()
+
+     - warning: This method is useful only in specialized circumstances.
+
+     - parameter className:  The class name of the object to be returned.
+     - parameter key:        The primary key of the desired object.
+
+     - returns: An object of type `DynamicObject` or `nil` if an object with the given primary key does not exist.
+
+     :nodoc:
+     */
+    public func dynamicObject(ofType typeName: String, forPrimaryKey key: Any) -> DynamicObject? {
+        return unsafeBitCast(RLMGetObject(rlmRealm, typeName, key) as! RLMObjectBase?, to: Optional<DynamicObject>.self)
+    }
+
+    // MARK: Notifications
+
+    /**
+     Adds a notification handler for changes made to this Realm, and returns a notification token.
+
+     Notification handlers are called after each write transaction is committed, independent of the thread or process.
+
+     Handler blocks are called on the same thread that they were added on, and may only be added on threads which are
+     currently within a run loop. Unless you are specifically creating and running a run loop on a background thread,
+     this will normally only be the main thread.
+
+     Notifications can't be delivered as long as the run loop is blocked by other activity. When notifications can't be
+     delivered instantly, multiple notifications may be coalesced.
+
+     You must retain the returned token for as long as you want updates to be sent to the block. To stop receiving
+     updates, call `invalidate()` on the token.
+
+     - parameter block: A block which is called to process Realm notifications. It receives the following parameters:
+                        `notification`: the incoming notification; `realm`: the Realm for which the notification
+                        occurred.
+
+     - returns: A token which must be held for as long as you wish to continue receiving change notifications.
+     */
+    public func observe(_ block: @escaping NotificationBlock) -> NotificationToken {
+        return rlmRealm.addNotificationBlock { rlmNotification, _ in
+            switch rlmNotification {
+            case RLMNotification.DidChange:
+                block(.didChange, self)
+            case RLMNotification.RefreshRequired:
+                block(.refreshRequired, self)
+            default:
+                fatalError("Unhandled notification type: \(rlmNotification)")
+            }
+        }
+    }
+
+    // MARK: Autorefresh and Refresh
+
+    /**
+     Set this property to `true` to automatically update this Realm when changes happen in other threads.
+
+     If set to `true` (the default), changes made on other threads will be reflected in this Realm on the next cycle of
+     the run loop after the changes are committed.  If set to `false`, you must manually call `refresh()` on the Realm
+     to update it to get the latest data.
+
+     Note that by default, background threads do not have an active run loop and you will need to manually call
+     `refresh()` in order to update to the latest version, even if `autorefresh` is set to `true`.
+
+     Even with this property enabled, you can still call `refresh()` at any time to update the Realm before the
+     automatic refresh would occur.
+
+     Notifications are sent when a write transaction is committed whether or not automatic refreshing is enabled.
+
+     Disabling `autorefresh` on a `Realm` without any strong references to it will not have any effect, and
+     `autorefresh` will revert back to `true` the next time the Realm is created. This is normally irrelevant as it
+     means that there is nothing to refresh (as managed `Object`s, `List`s, and `Results` have strong references to the
+     `Realm` that manages them), but it means that setting `autorefresh = false` in
+     `application(_:didFinishLaunchingWithOptions:)` and only later storing Realm objects will not work.
+
+     Defaults to `true`.
+     */
+    public var autorefresh: Bool {
+        get {
+            return rlmRealm.autorefresh
+        }
+        set {
+            rlmRealm.autorefresh = newValue
+        }
+    }
+
+    /**
+     Updates the Realm and outstanding objects managed by the Realm to point to the most recent data.
+
+     - returns: Whether there were any updates for the Realm. Note that `true` may be returned even if no data actually
+     changed.
+     */
+    @discardableResult
+    public func refresh() -> Bool {
+        return rlmRealm.refresh()
+    }
+
+    // MARK: Invalidation
+
+    /**
+     Invalidates all `Object`s, `Results`, `LinkingObjects`, and `List`s managed by the Realm.
+
+     A Realm holds a read lock on the version of the data accessed by it, so
+     that changes made to the Realm on different threads do not modify or delete the
+     data seen by this Realm. Calling this method releases the read lock,
+     allowing the space used on disk to be reused by later write transactions rather
+     than growing the file. This method should be called before performing long
+     blocking operations on a background thread on which you previously read data
+     from the Realm which you no longer need.
+
+     All `Object`, `Results` and `List` instances obtained from this `Realm` instance on the current thread are
+     invalidated. `Object`s and `Array`s cannot be used. `Results` will become empty. The Realm itself remains valid,
+     and a new read transaction is implicitly begun the next time data is read from the Realm.
+
+     Calling this method multiple times in a row without reading any data from the
+     Realm, or before ever reading any data from the Realm, is a no-op. This method
+     may not be called on a read-only Realm.
+     */
+    public func invalidate() {
+        rlmRealm.invalidate()
+    }
+
+    // MARK: Writing a Copy
+
+    /**
+     Writes a compacted and optionally encrypted copy of the Realm to the given local URL.
+
+     The destination file cannot already exist.
+
+     Note that if this method is called from within a write transaction, the *current* data is written, not the data
+     from the point when the previous write transaction was committed.
+
+     - parameter fileURL:       Local URL to save the Realm to.
+     - parameter encryptionKey: Optional 64-byte encryption key to encrypt the new file with.
+
+     - throws: An `NSError` if the copy could not be written.
+     */
+    public func writeCopy(toFile fileURL: URL, encryptionKey: Data? = nil) throws {
+        try rlmRealm.writeCopy(to: fileURL, encryptionKey: encryptionKey)
+    }
+
+    // MARK: Internal
+
+    internal var rlmRealm: RLMRealm
+
+    internal init(_ rlmRealm: RLMRealm) {
+        self.rlmRealm = rlmRealm
+    }
+}
+
+// MARK: Equatable
+
+extension Realm: Equatable {
+    /// Returns whether two `Realm` instances are equal.
+    public static func == (lhs: Realm, rhs: Realm) -> Bool {
+        return lhs.rlmRealm == rhs.rlmRealm
+    }
+}
+
+// MARK: Notifications
+
+extension Realm {
+    /// A notification indicating that changes were made to a Realm.
+    public enum Notification: String {
+        /**
+         This notification is posted when the data in a Realm has changed.
+
+         `didChange` is posted after a Realm has been refreshed to reflect a write transaction, This can happen when an
+         autorefresh occurs, `refresh()` is called, after an implicit refresh from `write(_:)`/`beginWrite()`, or after
+         a local write transaction is committed.
+         */
+        case didChange = "RLMRealmDidChangeNotification"
+
+        /**
+         This notification is posted when a write transaction has been committed to a Realm on a different thread for
+         the same file.
+
+         It is not posted if `autorefresh` is enabled, or if the Realm is refreshed before the notification has a chance
+         to run.
+
+         Realms with autorefresh disabled should normally install a handler for this notification which calls
+         `refresh()` after doing some work. Refreshing the Realm is optional, but not refreshing the Realm may lead to
+         large Realm files. This is because an extra copy of the data must be kept for the stale Realm.
+         */
+        case refreshRequired = "RLMRealmRefreshRequiredNotification"
+    }
+}
+
+/// The type of a block to run for notification purposes when the data in a Realm is modified.
+public typealias NotificationBlock = (_ notification: Realm.Notification, _ realm: Realm) -> Void