added iOS source code
[wl-app.git] / iOS / Pods / RealmSwift / RealmSwift / Realm.swift
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2014 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 /**
24  A `Realm` instance (also referred to as "a Realm") represents a Realm database.
25
26  Realms can either be stored on disk (see `init(path:)`) or in memory (see `Configuration`).
27
28  `Realm` instances are cached internally, and constructing equivalent `Realm` objects (for example, by using the same
29  path or identifier) produces limited overhead.
30
31  If you specifically want to ensure a `Realm` instance is destroyed (for example, if you wish to open a Realm, check
32  some property, and then possibly delete the Realm file and re-open it), place the code which uses the Realm within an
33  `autoreleasepool {}` and ensure you have no other strong references to it.
34
35  - warning: `Realm` instances are not thread safe and cannot be shared across threads or dispatch queues. You must
36  construct a new instance for each thread in which a Realm will be accessed. For dispatch queues, this means
37  that you must construct a new instance in each block which is dispatched, as a queue is not guaranteed to
38  run all of its blocks on the same thread.
39  */
40 public final class Realm {
41
42     // MARK: Properties
43
44     /// The `Schema` used by the Realm.
45     public var schema: Schema { return Schema(rlmRealm.schema) }
46
47     /// The `Configuration` value that was used to create the `Realm` instance.
48     public var configuration: Configuration { return Configuration.fromRLMRealmConfiguration(rlmRealm.configuration) }
49
50     /// Indicates if the Realm contains any objects.
51     public var isEmpty: Bool { return rlmRealm.isEmpty }
52
53     // MARK: Initializers
54
55     /**
56      Obtains an instance of the default Realm.
57
58      The default Realm is persisted as *default.realm* under the *Documents* directory of your Application on iOS, and
59      in your application's *Application Support* directory on OS X.
60
61      The default Realm is created using the default `Configuration`, which can be changed by setting the
62      `Realm.Configuration.defaultConfiguration` property to a new value.
63
64      - throws: An `NSError` if the Realm could not be initialized.
65      */
66     public convenience init() throws {
67         let rlmRealm = try RLMRealm(configuration: RLMRealmConfiguration.default())
68         self.init(rlmRealm)
69     }
70
71     /**
72      Obtains a `Realm` instance with the given configuration.
73
74      - parameter configuration: A configuration value to use when creating the Realm.
75
76      - throws: An `NSError` if the Realm could not be initialized.
77      */
78     public convenience init(configuration: Configuration) throws {
79         let rlmRealm = try RLMRealm(configuration: configuration.rlmConfiguration)
80         self.init(rlmRealm)
81     }
82
83     /**
84      Obtains a `Realm` instance persisted at a specified file URL.
85
86      - parameter fileURL: The local URL of the file the Realm should be saved at.
87
88      - throws: An `NSError` if the Realm could not be initialized.
89      */
90     public convenience init(fileURL: URL) throws {
91         var configuration = Configuration.defaultConfiguration
92         configuration.fileURL = fileURL
93         try self.init(configuration: configuration)
94     }
95
96     // MARK: Async
97
98     /**
99      Asynchronously open a Realm and deliver it to a block on the given queue.
100
101      Opening a Realm asynchronously will perform all work needed to get the Realm to
102      a usable state (such as running potentially time-consuming migrations) on a
103      background thread before dispatching to the given queue. In addition,
104      synchronized Realms wait for all remote content available at the time the
105      operation began to be downloaded and available locally.
106
107      - parameter configuration: A configuration object to use when opening the Realm.
108      - parameter callbackQueue: The dispatch queue on which the callback should be run.
109      - parameter callback:      A callback block. If the Realm was successfully opened, an
110                                 it will be passed in as an argument.
111                                 Otherwise, a `Swift.Error` describing what went wrong will be
112                                 passed to the block instead.
113
114      - note: The returned Realm is confined to the thread on which it was created.
115              Because GCD does not guarantee that queues will always use the same
116              thread, accessing the returned Realm outside the callback block (even if
117              accessed from `callbackQueue`) is unsafe.
118      */
119     public static func asyncOpen(configuration: Realm.Configuration = .defaultConfiguration,
120                                  callbackQueue: DispatchQueue = .main,
121                                  callback: @escaping (Realm?, Swift.Error?) -> Void) {
122         RLMRealm.asyncOpen(with: configuration.rlmConfiguration, callbackQueue: callbackQueue) { rlmRealm, error in
123             callback(rlmRealm.flatMap(Realm.init), error)
124         }
125     }
126
127     // MARK: Transactions
128
129     /**
130      Performs actions contained within the given block inside a write transaction.
131
132      If the block throws an error, the transaction will be canceled and any
133      changes made before the error will be rolled back.
134
135      Only one write transaction can be open at a time for each Realm file. Write
136      transactions cannot be nested, and trying to begin a write transaction on a
137      Realm which is already in a write transaction will throw an exception.
138      Calls to `write` from `Realm` instances for the same Realm file in other
139      threads or other processes will block until the current write transaction
140      completes or is cancelled.
141
142      Before beginning the write transaction, `write` updates the `Realm`
143      instance to the latest Realm version, as if `refresh()` had been called,
144      and generates notifications if applicable. This has no effect if the Realm
145      was already up to date.
146
147      - parameter block: The block containing actions to perform.
148
149      - throws: An `NSError` if the transaction could not be completed successfully.
150                If `block` throws, the function throws the propagated `ErrorType` instead.
151      */
152     public func write(_ block: (() throws -> Void)) throws {
153         beginWrite()
154         do {
155             try block()
156         } catch let error {
157             if isInWriteTransaction { cancelWrite() }
158             throw error
159         }
160         if isInWriteTransaction { try commitWrite() }
161     }
162
163     /**
164      Begins a write transaction on the Realm.
165
166      Only one write transaction can be open at a time for each Realm file. Write
167      transactions cannot be nested, and trying to begin a write transaction on a
168      Realm which is already in a write transaction will throw an exception.
169      Calls to `beginWrite` from `Realm` instances for the same Realm file in
170      other threads or other processes will block until the current write
171      transaction completes or is cancelled.
172
173      Before beginning the write transaction, `beginWrite` updates the `Realm`
174      instance to the latest Realm version, as if `refresh()` had been called,
175      and generates notifications if applicable. This has no effect if the Realm
176      was already up to date.
177
178      It is rarely a good idea to have write transactions span multiple cycles of
179      the run loop, but if you do wish to do so you will need to ensure that the
180      Realm participating in the write transaction is kept alive until the write
181      transaction is committed.
182      */
183     public func beginWrite() {
184         rlmRealm.beginWriteTransaction()
185     }
186
187     /**
188      Commits all write operations in the current write transaction, and ends
189      the transaction.
190
191      After saving the changes and completing the write transaction, all
192      notification blocks registered on this specific `Realm` instance are called
193      synchronously. Notification blocks for `Realm` instances on other threads
194      and blocks registered for any Realm collection (including those on the
195      current thread) are scheduled to be called synchronously.
196
197      You can skip notifiying specific notification blocks about the changes made
198      in this write transaction by passing in their associated notification
199      tokens. This is primarily useful when the write transaction is saving
200      changes already made in the UI and you do not want to have the notification
201      block attempt to re-apply the same changes.
202
203      The tokens passed to this function must be for notifications for this Realm
204      which were added on the same thread as the write transaction is being
205      performed on. Notifications for different threads cannot be skipped using
206      this method.
207
208      - warning: This method may only be called during a write transaction.
209
210      - throws: An `NSError` if the transaction could not be written due to
211                running out of disk space or other i/o errors.
212      */
213     public func commitWrite(withoutNotifying tokens: [NotificationToken] = []) throws {
214         try rlmRealm.commitWriteTransactionWithoutNotifying(tokens)
215     }
216
217     /**
218      Reverts all writes made in the current write transaction and ends the transaction.
219
220      This rolls back all objects in the Realm to the state they were in at the
221      beginning of the write transaction, and then ends the transaction.
222
223      This restores the data for deleted objects, but does not revive invalidated
224      object instances. Any `Object`s which were added to the Realm will be
225      invalidated rather than becoming unmanaged.
226
227      Given the following code:
228
229      ```swift
230      let oldObject = objects(ObjectType).first!
231      let newObject = ObjectType()
232
233      realm.beginWrite()
234      realm.add(newObject)
235      realm.delete(oldObject)
236      realm.cancelWrite()
237      ```
238
239      Both `oldObject` and `newObject` will return `true` for `isInvalidated`,
240      but re-running the query which provided `oldObject` will once again return
241      the valid object.
242
243      KVO observers on any objects which were modified during the transaction
244      will be notified about the change back to their initial values, but no
245      other notifcations are produced by a cancelled write transaction.
246
247      - warning: This method may only be called during a write transaction.
248      */
249     public func cancelWrite() {
250         rlmRealm.cancelWriteTransaction()
251     }
252
253     /**
254      Indicates whether the Realm is currently in a write transaction.
255
256      - warning:  Do not simply check this property and then start a write transaction whenever an object needs to be
257                  created, updated, or removed. Doing so might cause a large number of write transactions to be created,
258                  degrading performance. Instead, always prefer performing multiple updates during a single transaction.
259      */
260     public var isInWriteTransaction: Bool {
261         return rlmRealm.inWriteTransaction
262     }
263
264     // MARK: Adding and Creating objects
265
266     /**
267      Adds or updates an existing object into the Realm.
268
269      Only pass `true` to `update` if the object has a primary key. If no object exists in the Realm with the same
270      primary key value, the object is inserted. Otherwise, the existing object is updated with any changed values.
271
272      When added, all child relationships referenced by this object will also be added to the Realm if they are not
273      already in it. If the object or any related objects are already being managed by a different Realm an error will be
274      thrown. Instead, use one of the `create` functions to insert a copy of a managed object into a different Realm.
275
276      The object to be added must be valid and cannot have been previously deleted from a Realm (i.e. `isInvalidated`
277      must be `false`).
278
279      - parameter object: The object to be added to this Realm.
280      - parameter update: If `true`, the Realm will try to find an existing copy of the object (with the same primary
281                          key), and update it. Otherwise, the object will be added.
282      */
283     public func add(_ object: Object, update: Bool = false) {
284         if update && object.objectSchema.primaryKeyProperty == nil {
285             throwRealmException("'\(object.objectSchema.className)' does not have a primary key and can not be updated")
286         }
287         RLMAddObjectToRealm(object, rlmRealm, update)
288     }
289
290     /**
291      Adds or updates all the objects in a collection into the Realm.
292
293      - see: `add(_:update:)`
294
295      - warning: This method may only be called during a write transaction.
296
297      - parameter objects: A sequence which contains objects to be added to the Realm.
298      - parameter update: If `true`, objects that are already in the Realm will be updated instead of added anew.
299      */
300     public func add<S: Sequence>(_ objects: S, update: Bool = false) where S.Iterator.Element: Object {
301         for obj in objects {
302             add(obj, update: update)
303         }
304     }
305
306     /**
307      Creates or updates a Realm object with a given value, adding it to the Realm and returning it.
308
309      You may only pass `true` to `update` if the object has a primary key. If no object exists
310      in the Realm with the same primary key value, the object is inserted. Otherwise, the
311      existing object is updated with any changed values.
312
313      The `value` argument can be a Realm object, a key-value coding compliant object, an array
314      or dictionary returned from the methods in `NSJSONSerialization`, or an `Array` containing
315      one element for each managed property. Do not pass in a `LinkingObjects` instance, either
316      by itself or as a member of a collection.
317
318      If the object is being created, all required properties that were not defined with default
319      values must be given initial values through the `value` argument. Otherwise, an Objective-C
320      exception will be thrown.
321
322      If the object is being updated, all properties defined in its schema will be set by copying
323      from `value` using key-value coding. If the `value` argument does not respond to `value(forKey:)`
324      for a given property name (or getter name, if defined), that value will remain untouched.
325      Nullable properties on the object can be set to nil by using `NSNull` as the updated value,
326      or (if you are passing in an instance of an `Object` subclass) setting the corresponding
327      property on `value` to nil.
328
329      If the `value` argument is an array, all properties must be present, valid and in the same
330      order as the properties defined in the model.
331
332      - warning: This method may only be called during a write transaction.
333
334      - parameter type:   The type of the object to create.
335      - parameter value:  The value used to populate the object.
336      - parameter update: If `true`, the Realm will try to find an existing copy of the object (with the same primary
337                          key), and update it. Otherwise, the object will be added.
338
339      - returns: The newly created object.
340      */
341     @discardableResult
342     public func create<T: Object>(_ type: T.Type, value: Any = [:], update: Bool = false) -> T {
343         let typeName = (type as Object.Type).className()
344         if update && schema[typeName]?.primaryKeyProperty == nil {
345             throwRealmException("'\(typeName)' does not have a primary key and can not be updated")
346         }
347         return unsafeDowncast(RLMCreateObjectInRealmWithValue(rlmRealm, typeName, value, update), to: T.self)
348     }
349
350     /**
351      This method is useful only in specialized circumstances, for example, when building
352      components that integrate with Realm. If you are simply building an app on Realm, it is
353      recommended to use the typed method `create(_:value:update:)`.
354
355      Creates or updates an object with the given class name and adds it to the `Realm`, populating
356      the object with the given value.
357
358      You may only pass `true` to `update` if the object has a primary key. If no object exists
359      in the Realm with the same primary key value, the object is inserted. Otherwise, the
360      existing object is updated with any changed values.
361
362      The `value` argument can be a Realm object, a key-value coding compliant object, an array
363      or dictionary returned from the methods in `NSJSONSerialization`, or an `Array` containing
364      one element for each managed property. Do not pass in a `LinkingObjects` instance, either
365      by itself or as a member of a collection.
366
367      If the object is being created, all required properties that were not defined with default
368      values must be given initial values through the `value` argument. Otherwise, an Objective-C
369      exception will be thrown.
370
371      If the object is being updated, all properties defined in its schema will be set by copying
372      from `value` using key-value coding. If the `value` argument does not respond to `value(forKey:)`
373      for a given property name (or getter name, if defined), that value will remain untouched.
374      Nullable properties on the object can be set to nil by using `NSNull` as the updated value.
375
376      If the `value` argument is an array, all properties must be present, valid and in the same
377      order as the properties defined in the model.
378
379      - warning: This method can only be called during a write transaction.
380
381      - parameter className:  The class name of the object to create.
382      - parameter value:      The value used to populate the object.
383      - parameter update:     If true will try to update existing objects with the same primary key.
384
385      - returns: The created object.
386
387      :nodoc:
388      */
389     @discardableResult
390     public func dynamicCreate(_ typeName: String, value: Any = [:], update: Bool = false) -> DynamicObject {
391         if update && schema[typeName]?.primaryKeyProperty == nil {
392             throwRealmException("'\(typeName)' does not have a primary key and can not be updated")
393         }
394         return noWarnUnsafeBitCast(RLMCreateObjectInRealmWithValue(rlmRealm, typeName, value, update),
395                                    to: DynamicObject.self)
396     }
397
398     // MARK: Deleting objects
399
400     /**
401      Deletes an object from the Realm. Once the object is deleted it is considered invalidated.
402
403      - warning: This method may only be called during a write transaction.
404
405      - parameter object: The object to be deleted.
406      */
407     public func delete(_ object: Object) {
408         RLMDeleteObjectFromRealm(object, rlmRealm)
409     }
410
411     /**
412      Deletes zero or more objects from the Realm.
413
414      Do not pass in a slice to a `Results` or any other auto-updating Realm collection
415      type (for example, the type returned by the Swift `suffix(_:)` standard library
416      method). Instead, make a copy of the objects to delete using `Array()`, and pass
417      that instead. Directly passing in a view into an auto-updating collection may
418      result in 'index out of bounds' exceptions being thrown.
419
420      - warning: This method may only be called during a write transaction.
421
422      - parameter objects:   The objects to be deleted. This can be a `List<Object>`,
423                             `Results<Object>`, or any other Swift `Sequence` whose
424                             elements are `Object`s (subject to the caveats above).
425      */
426     public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: Object {
427         for obj in objects {
428             delete(obj)
429         }
430     }
431
432     /**
433      Deletes zero or more objects from the Realm.
434
435      - warning: This method may only be called during a write transaction.
436
437      - parameter objects: A list of objects to delete.
438
439      :nodoc:
440      */
441     public func delete<Element: Object>(_ objects: List<Element>) {
442         rlmRealm.deleteObjects(objects._rlmArray)
443     }
444
445     /**
446      Deletes zero or more objects from the Realm.
447
448      - warning: This method may only be called during a write transaction.
449
450      - parameter objects: A `Results` containing the objects to be deleted.
451
452      :nodoc:
453      */
454     public func delete<Element: Object>(_ objects: Results<Element>) {
455         rlmRealm.deleteObjects(objects.rlmResults)
456     }
457
458     /**
459      Deletes all objects from the Realm.
460
461      - warning: This method may only be called during a write transaction.
462      */
463     public func deleteAll() {
464         RLMDeleteAllObjectsFromRealm(rlmRealm)
465     }
466
467     // MARK: Object Retrieval
468
469     /**
470      Returns all objects of the given type stored in the Realm.
471
472      - parameter type: The type of the objects to be returned.
473
474      - returns: A `Results` containing the objects.
475      */
476     public func objects<Element: Object>(_ type: Element.Type) -> Results<Element> {
477         return Results(RLMGetObjects(rlmRealm, type.className(), nil))
478     }
479
480     /**
481      This method is useful only in specialized circumstances, for example, when building
482      components that integrate with Realm. If you are simply building an app on Realm, it is
483      recommended to use the typed method `objects(type:)`.
484
485      Returns all objects for a given class name in the Realm.
486
487      - parameter typeName: The class name of the objects to be returned.
488      - returns: All objects for the given class name as dynamic objects
489
490      :nodoc:
491      */
492     public func dynamicObjects(_ typeName: String) -> Results<DynamicObject> {
493         return Results<DynamicObject>(RLMGetObjects(rlmRealm, typeName, nil))
494     }
495
496     /**
497      Retrieves the single instance of a given object type with the given primary key from the Realm.
498
499      This method requires that `primaryKey()` be overridden on the given object class.
500
501      - see: `Object.primaryKey()`
502
503      - parameter type: The type of the object to be returned.
504      - parameter key:  The primary key of the desired object.
505
506      - returns: An object of type `type`, or `nil` if no instance with the given primary key exists.
507      */
508     public func object<Element: Object, KeyType>(ofType type: Element.Type, forPrimaryKey key: KeyType) -> Element? {
509         return unsafeBitCast(RLMGetObject(rlmRealm, (type as Object.Type).className(),
510                                           dynamicBridgeCast(fromSwift: key)) as! RLMObjectBase?,
511                              to: Optional<Element>.self)
512     }
513
514     /**
515      This method is useful only in specialized circumstances, for example, when building
516      components that integrate with Realm. If you are simply building an app on Realm, it is
517      recommended to use the typed method `objectForPrimaryKey(_:key:)`.
518
519      Get a dynamic object with the given class name and primary key.
520
521      Returns `nil` if no object exists with the given class name and primary key.
522
523      This method requires that `primaryKey()` be overridden on the given subclass.
524
525      - see: Object.primaryKey()
526
527      - warning: This method is useful only in specialized circumstances.
528
529      - parameter className:  The class name of the object to be returned.
530      - parameter key:        The primary key of the desired object.
531
532      - returns: An object of type `DynamicObject` or `nil` if an object with the given primary key does not exist.
533
534      :nodoc:
535      */
536     public func dynamicObject(ofType typeName: String, forPrimaryKey key: Any) -> DynamicObject? {
537         return unsafeBitCast(RLMGetObject(rlmRealm, typeName, key) as! RLMObjectBase?, to: Optional<DynamicObject>.self)
538     }
539
540     // MARK: Notifications
541
542     /**
543      Adds a notification handler for changes made to this Realm, and returns a notification token.
544
545      Notification handlers are called after each write transaction is committed, independent of the thread or process.
546
547      Handler blocks are called on the same thread that they were added on, and may only be added on threads which are
548      currently within a run loop. Unless you are specifically creating and running a run loop on a background thread,
549      this will normally only be the main thread.
550
551      Notifications can't be delivered as long as the run loop is blocked by other activity. When notifications can't be
552      delivered instantly, multiple notifications may be coalesced.
553
554      You must retain the returned token for as long as you want updates to be sent to the block. To stop receiving
555      updates, call `invalidate()` on the token.
556
557      - parameter block: A block which is called to process Realm notifications. It receives the following parameters:
558                         `notification`: the incoming notification; `realm`: the Realm for which the notification
559                         occurred.
560
561      - returns: A token which must be held for as long as you wish to continue receiving change notifications.
562      */
563     public func observe(_ block: @escaping NotificationBlock) -> NotificationToken {
564         return rlmRealm.addNotificationBlock { rlmNotification, _ in
565             switch rlmNotification {
566             case RLMNotification.DidChange:
567                 block(.didChange, self)
568             case RLMNotification.RefreshRequired:
569                 block(.refreshRequired, self)
570             default:
571                 fatalError("Unhandled notification type: \(rlmNotification)")
572             }
573         }
574     }
575
576     // MARK: Autorefresh and Refresh
577
578     /**
579      Set this property to `true` to automatically update this Realm when changes happen in other threads.
580
581      If set to `true` (the default), changes made on other threads will be reflected in this Realm on the next cycle of
582      the run loop after the changes are committed.  If set to `false`, you must manually call `refresh()` on the Realm
583      to update it to get the latest data.
584
585      Note that by default, background threads do not have an active run loop and you will need to manually call
586      `refresh()` in order to update to the latest version, even if `autorefresh` is set to `true`.
587
588      Even with this property enabled, you can still call `refresh()` at any time to update the Realm before the
589      automatic refresh would occur.
590
591      Notifications are sent when a write transaction is committed whether or not automatic refreshing is enabled.
592
593      Disabling `autorefresh` on a `Realm` without any strong references to it will not have any effect, and
594      `autorefresh` will revert back to `true` the next time the Realm is created. This is normally irrelevant as it
595      means that there is nothing to refresh (as managed `Object`s, `List`s, and `Results` have strong references to the
596      `Realm` that manages them), but it means that setting `autorefresh = false` in
597      `application(_:didFinishLaunchingWithOptions:)` and only later storing Realm objects will not work.
598
599      Defaults to `true`.
600      */
601     public var autorefresh: Bool {
602         get {
603             return rlmRealm.autorefresh
604         }
605         set {
606             rlmRealm.autorefresh = newValue
607         }
608     }
609
610     /**
611      Updates the Realm and outstanding objects managed by the Realm to point to the most recent data.
612
613      - returns: Whether there were any updates for the Realm. Note that `true` may be returned even if no data actually
614      changed.
615      */
616     @discardableResult
617     public func refresh() -> Bool {
618         return rlmRealm.refresh()
619     }
620
621     // MARK: Invalidation
622
623     /**
624      Invalidates all `Object`s, `Results`, `LinkingObjects`, and `List`s managed by the Realm.
625
626      A Realm holds a read lock on the version of the data accessed by it, so
627      that changes made to the Realm on different threads do not modify or delete the
628      data seen by this Realm. Calling this method releases the read lock,
629      allowing the space used on disk to be reused by later write transactions rather
630      than growing the file. This method should be called before performing long
631      blocking operations on a background thread on which you previously read data
632      from the Realm which you no longer need.
633
634      All `Object`, `Results` and `List` instances obtained from this `Realm` instance on the current thread are
635      invalidated. `Object`s and `Array`s cannot be used. `Results` will become empty. The Realm itself remains valid,
636      and a new read transaction is implicitly begun the next time data is read from the Realm.
637
638      Calling this method multiple times in a row without reading any data from the
639      Realm, or before ever reading any data from the Realm, is a no-op. This method
640      may not be called on a read-only Realm.
641      */
642     public func invalidate() {
643         rlmRealm.invalidate()
644     }
645
646     // MARK: Writing a Copy
647
648     /**
649      Writes a compacted and optionally encrypted copy of the Realm to the given local URL.
650
651      The destination file cannot already exist.
652
653      Note that if this method is called from within a write transaction, the *current* data is written, not the data
654      from the point when the previous write transaction was committed.
655
656      - parameter fileURL:       Local URL to save the Realm to.
657      - parameter encryptionKey: Optional 64-byte encryption key to encrypt the new file with.
658
659      - throws: An `NSError` if the copy could not be written.
660      */
661     public func writeCopy(toFile fileURL: URL, encryptionKey: Data? = nil) throws {
662         try rlmRealm.writeCopy(to: fileURL, encryptionKey: encryptionKey)
663     }
664
665     // MARK: Internal
666
667     internal var rlmRealm: RLMRealm
668
669     internal init(_ rlmRealm: RLMRealm) {
670         self.rlmRealm = rlmRealm
671     }
672 }
673
674 // MARK: Equatable
675
676 extension Realm: Equatable {
677     /// Returns whether two `Realm` instances are equal.
678     public static func == (lhs: Realm, rhs: Realm) -> Bool {
679         return lhs.rlmRealm == rhs.rlmRealm
680     }
681 }
682
683 // MARK: Notifications
684
685 extension Realm {
686     /// A notification indicating that changes were made to a Realm.
687     public enum Notification: String {
688         /**
689          This notification is posted when the data in a Realm has changed.
690
691          `didChange` is posted after a Realm has been refreshed to reflect a write transaction, This can happen when an
692          autorefresh occurs, `refresh()` is called, after an implicit refresh from `write(_:)`/`beginWrite()`, or after
693          a local write transaction is committed.
694          */
695         case didChange = "RLMRealmDidChangeNotification"
696
697         /**
698          This notification is posted when a write transaction has been committed to a Realm on a different thread for
699          the same file.
700
701          It is not posted if `autorefresh` is enabled, or if the Realm is refreshed before the notification has a chance
702          to run.
703
704          Realms with autorefresh disabled should normally install a handler for this notification which calls
705          `refresh()` after doing some work. Refreshing the Realm is optional, but not refreshing the Realm may lead to
706          large Realm files. This is because an extra copy of the data must be kept for the stale Realm.
707          */
708         case refreshRequired = "RLMRealmRefreshRequiredNotification"
709     }
710 }
711
712 /// The type of a block to run for notification purposes when the data in a Realm is modified.
713 public typealias NotificationBlock = (_ notification: Realm.Notification, _ realm: Realm) -> Void