added iOS source code
[wl-app.git] / iOS / Pods / RealmSwift / RealmSwift / List.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 /// :nodoc:
24 /// Internal class. Do not use directly.
25 public class ListBase: RLMListBase {
26     // Printable requires a description property defined in Swift (and not obj-c),
27     // and it has to be defined as override, which can't be done in a
28     // generic class.
29     /// Returns a human-readable description of the objects contained in the List.
30     @objc public override var description: String {
31         return descriptionWithMaxDepth(RLMDescriptionMaxDepth)
32     }
33
34     @objc private func descriptionWithMaxDepth(_ depth: UInt) -> String {
35         return RLMDescriptionWithMaxDepth("List", _rlmArray, depth)
36     }
37
38     /// Returns the number of objects in this List.
39     public var count: Int { return Int(_rlmArray.count) }
40 }
41
42 /**
43  `List` is the container type in Realm used to define to-many relationships.
44
45  Like Swift's `Array`, `List` is a generic type that is parameterized on the type of `Object` it stores.
46
47  Unlike Swift's native collections, `List`s are reference types, and are only immutable if the Realm that manages them
48  is opened as read-only.
49
50  Lists can be filtered and sorted with the same predicates as `Results<Element>`.
51
52  Properties of `List` type defined on `Object` subclasses must be declared as `let` and cannot be `dynamic`.
53  */
54 public final class List<Element: RealmCollectionValue>: ListBase {
55
56     // MARK: Properties
57
58     /// The Realm which manages the list, or `nil` if the list is unmanaged.
59     public var realm: Realm? {
60         return _rlmArray.realm.map { Realm($0) }
61     }
62
63     /// Indicates if the list can no longer be accessed.
64     public var isInvalidated: Bool { return _rlmArray.isInvalidated }
65
66     // MARK: Initializers
67
68     /// Creates a `List` that holds Realm model objects of type `Element`.
69     public override init() {
70         super.init(array: Element._rlmArray())
71     }
72
73     internal init(rlmArray: RLMArray<AnyObject>) {
74         super.init(array: rlmArray)
75     }
76
77     // MARK: Index Retrieval
78
79     /**
80      Returns the index of an object in the list, or `nil` if the object is not present.
81
82      - parameter object: An object to find.
83      */
84     public func index(of object: Element) -> Int? {
85         return notFoundToNil(index: _rlmArray.index(of: dynamicBridgeCast(fromSwift: object) as AnyObject))
86     }
87
88     /**
89      Returns the index of the first object in the list matching the predicate, or `nil` if no objects match.
90
91      - parameter predicate: The predicate with which to filter the objects.
92     */
93     public func index(matching predicate: NSPredicate) -> Int? {
94         return notFoundToNil(index: _rlmArray.indexOfObject(with: predicate))
95     }
96
97     /**
98      Returns the index of the first object in the list matching the predicate, or `nil` if no objects match.
99
100      - parameter predicateFormat: A predicate format string, optionally followed by a variable number of arguments.
101     */
102     public func index(matching predicateFormat: String, _ args: Any...) -> Int? {
103         return index(matching: NSPredicate(format: predicateFormat, argumentArray: unwrapOptionals(in: args)))
104     }
105
106     // MARK: Object Retrieval
107
108     /**
109      Returns the object at the given index (get), or replaces the object at the given index (set).
110
111      - warning: You can only set an object during a write transaction.
112
113      - parameter index: The index of the object to retrieve or replace.
114      */
115     public subscript(position: Int) -> Element {
116         get {
117             throwForNegativeIndex(position)
118             return dynamicBridgeCast(fromObjectiveC: _rlmArray.object(at: UInt(position)))
119         }
120         set {
121             throwForNegativeIndex(position)
122             _rlmArray.replaceObject(at: UInt(position), with: dynamicBridgeCast(fromSwift: newValue) as AnyObject)
123         }
124     }
125
126     /// Returns the first object in the list, or `nil` if the list is empty.
127     public var first: Element? { return _rlmArray.firstObject().map(dynamicBridgeCast) }
128
129     /// Returns the last object in the list, or `nil` if the list is empty.
130     public var last: Element? { return _rlmArray.lastObject().map(dynamicBridgeCast) }
131
132     // MARK: KVC
133
134     /**
135      Returns an `Array` containing the results of invoking `valueForKey(_:)` using `key` on each of the collection's
136      objects.
137      */
138     @nonobjc public func value(forKey key: String) -> [AnyObject] {
139         return _rlmArray.value(forKeyPath: key)! as! [AnyObject]
140     }
141
142     /**
143      Returns an `Array` containing the results of invoking `valueForKeyPath(_:)` using `keyPath` on each of the
144      collection's objects.
145
146      - parameter keyPath: The key path to the property whose values are desired.
147      */
148     @nonobjc public func value(forKeyPath keyPath: String) -> [AnyObject] {
149         return _rlmArray.value(forKeyPath: keyPath) as! [AnyObject]
150     }
151
152     /**
153      Invokes `setValue(_:forKey:)` on each of the collection's objects using the specified `value` and `key`.
154
155      - warning: This method can only be called during a write transaction.
156
157      - parameter value: The object value.
158      - parameter key:   The name of the property whose value should be set on each object.
159     */
160     public override func setValue(_ value: Any?, forKey key: String) {
161         return _rlmArray.setValue(value, forKeyPath: key)
162     }
163
164     // MARK: Filtering
165
166     /**
167      Returns a `Results` containing all objects matching the given predicate in the list.
168
169      - parameter predicateFormat: A predicate format string, optionally followed by a variable number of arguments.
170     */
171     public func filter(_ predicateFormat: String, _ args: Any...) -> Results<Element> {
172         return Results<Element>(_rlmArray.objects(with: NSPredicate(format: predicateFormat,
173                                                               argumentArray: unwrapOptionals(in: args))))
174     }
175
176     /**
177      Returns a `Results` containing all objects matching the given predicate in the list.
178
179      - parameter predicate: The predicate with which to filter the objects.
180      */
181     public func filter(_ predicate: NSPredicate) -> Results<Element> {
182         return Results<Element>(_rlmArray.objects(with: predicate))
183     }
184
185     // MARK: Sorting
186
187     /**
188      Returns a `Results` containing the objects in the list, but sorted.
189
190      Objects are sorted based on the values of the given key path. For example, to sort a list of `Student`s from
191      youngest to oldest based on their `age` property, you might call
192      `students.sorted(byKeyPath: "age", ascending: true)`.
193
194      - warning: Lists may only be sorted by properties of boolean, `Date`, `NSDate`, single and double-precision
195                 floating point, integer, and string types.
196
197      - parameter keyPath:  The key path to sort by.
198      - parameter ascending: The direction to sort in.
199      */
200     public func sorted(byKeyPath keyPath: String, ascending: Bool = true) -> Results<Element> {
201         return sorted(by: [SortDescriptor(keyPath: keyPath, ascending: ascending)])
202     }
203
204     /**
205      Returns a `Results` containing the objects in the list, but sorted.
206
207      - warning: Lists may only be sorted by properties of boolean, `Date`, `NSDate`, single and double-precision
208                 floating point, integer, and string types.
209
210      - see: `sorted(byKeyPath:ascending:)`
211     */
212     public func sorted<S: Sequence>(by sortDescriptors: S) -> Results<Element>
213         where S.Iterator.Element == SortDescriptor {
214             return Results<Element>(_rlmArray.sortedResults(using: sortDescriptors.map { $0.rlmSortDescriptorValue }))
215     }
216
217     // MARK: Aggregate Operations
218
219     /**
220      Returns the minimum (lowest) value of the given property among all the objects in the list, or `nil` if the list is
221      empty.
222
223      - warning: Only a property whose type conforms to the `MinMaxType` protocol can be specified.
224
225      - parameter property: The name of a property whose minimum value is desired.
226      */
227     public func min<T: MinMaxType>(ofProperty property: String) -> T? {
228         return _rlmArray.min(ofProperty: property).map(dynamicBridgeCast)
229     }
230
231     /**
232      Returns the maximum (highest) value of the given property among all the objects in the list, or `nil` if the list
233      is empty.
234
235      - warning: Only a property whose type conforms to the `MinMaxType` protocol can be specified.
236
237      - parameter property: The name of a property whose maximum value is desired.
238      */
239     public func max<T: MinMaxType>(ofProperty property: String) -> T? {
240         return _rlmArray.max(ofProperty: property).map(dynamicBridgeCast)
241     }
242
243     /**
244      Returns the sum of the values of a given property over all the objects in the list.
245
246      - warning: Only a property whose type conforms to the `AddableType` protocol can be specified.
247
248      - parameter property: The name of a property whose values should be summed.
249      */
250     public func sum<T: AddableType>(ofProperty property: String) -> T {
251         return dynamicBridgeCast(fromObjectiveC: _rlmArray.sum(ofProperty: property))
252     }
253
254     /**
255      Returns the average value of a given property over all the objects in the list, or `nil` if the list is empty.
256
257      - warning: Only a property whose type conforms to the `AddableType` protocol can be specified.
258
259      - parameter property: The name of a property whose average value should be calculated.
260      */
261     public func average(ofProperty property: String) -> Double? {
262         return _rlmArray.average(ofProperty: property).map(dynamicBridgeCast)
263     }
264
265     // MARK: Mutation
266
267     /**
268      Appends the given object to the end of the list.
269
270      If the object is managed by a different Realm than the receiver, a copy is made and added to the Realm managing
271      the receiver.
272
273      - warning: This method may only be called during a write transaction.
274
275      - parameter object: An object.
276      */
277     public func append(_ object: Element) {
278         _rlmArray.add(dynamicBridgeCast(fromSwift: object) as AnyObject)
279     }
280
281     /**
282      Appends the objects in the given sequence to the end of the list.
283
284      - warning: This method may only be called during a write transaction.
285     */
286     public func append<S: Sequence>(objectsIn objects: S) where S.Iterator.Element == Element {
287         for obj in objects {
288             _rlmArray.add(dynamicBridgeCast(fromSwift: obj) as AnyObject)
289         }
290     }
291
292     /**
293      Inserts an object at the given index.
294
295      - warning: This method may only be called during a write transaction.
296
297      - warning: This method will throw an exception if called with an invalid index.
298
299      - parameter object: An object.
300      - parameter index:  The index at which to insert the object.
301      */
302     public func insert(_ object: Element, at index: Int) {
303         throwForNegativeIndex(index)
304         _rlmArray.insert(dynamicBridgeCast(fromSwift: object) as AnyObject, at: UInt(index))
305     }
306
307     /**
308      Removes an object at the given index. The object is not removed from the Realm that manages it.
309
310      - warning: This method may only be called during a write transaction.
311
312      - warning: This method will throw an exception if called with an invalid index.
313
314      - parameter index: The index at which to remove the object.
315      */
316     public func remove(at index: Int) {
317         throwForNegativeIndex(index)
318         _rlmArray.removeObject(at: UInt(index))
319     }
320
321     /**
322      Removes all objects from the list. The objects are not removed from the Realm that manages them.
323
324      - warning: This method may only be called during a write transaction.
325      */
326     public func removeAll() {
327         _rlmArray.removeAllObjects()
328     }
329
330     /**
331      Replaces an object at the given index with a new object.
332
333      - warning: This method may only be called during a write transaction.
334
335      - warning: This method will throw an exception if called with an invalid index.
336
337      - parameter index:  The index of the object to be replaced.
338      - parameter object: An object.
339      */
340     public func replace(index: Int, object: Element) {
341         throwForNegativeIndex(index)
342         _rlmArray.replaceObject(at: UInt(index), with: dynamicBridgeCast(fromSwift: object) as AnyObject)
343     }
344
345     /**
346      Moves the object at the given source index to the given destination index.
347
348      - warning: This method may only be called during a write transaction.
349
350      - warning: This method will throw an exception if called with invalid indices.
351
352      - parameter from:  The index of the object to be moved.
353      - parameter to:    index to which the object at `from` should be moved.
354      */
355     public func move(from: Int, to: Int) {
356         throwForNegativeIndex(from)
357         throwForNegativeIndex(to)
358         _rlmArray.moveObject(at: UInt(from), to: UInt(to))
359     }
360
361     /**
362      Exchanges the objects in the list at given indices.
363
364      - warning: This method may only be called during a write transaction.
365
366      - warning: This method will throw an exception if called with invalid indices.
367
368      - parameter index1: The index of the object which should replace the object at index `index2`.
369      - parameter index2: The index of the object which should replace the object at index `index1`.
370      */
371     public func swapAt(_ index1: Int, _ index2: Int) {
372         throwForNegativeIndex(index1, parameterName: "index1")
373         throwForNegativeIndex(index2, parameterName: "index2")
374         _rlmArray.exchangeObject(at: UInt(index1), withObjectAt: UInt(index2))
375     }
376
377     // MARK: Notifications
378
379     /**
380      Registers a block to be called each time the collection changes.
381
382      The block will be asynchronously called with the initial results, and then called again after each write
383      transaction which changes either any of the objects in the collection, or which objects are in the collection.
384
385      The `change` parameter that is passed to the block reports, in the form of indices within the collection, which of
386      the objects were added, removed, or modified during each write transaction. See the `RealmCollectionChange`
387      documentation for more information on the change information supplied and an example of how to use it to update a
388      `UITableView`.
389
390      At the time when the block is called, the collection will be fully evaluated and up-to-date, and as long as you do
391      not perform a write transaction on the same thread or explicitly call `realm.refresh()`, accessing it will never
392      perform blocking work.
393
394      Notifications are delivered via the standard run loop, and so can't be delivered while the run loop is blocked by
395      other activity. When notifications can't be delivered instantly, multiple notifications may be coalesced into a
396      single notification. This can include the notification with the initial collection.
397
398      For example, the following code performs a write transaction immediately after adding the notification block, so
399      there is no opportunity for the initial notification to be delivered first. As a result, the initial notification
400      will reflect the state of the Realm after the write transaction.
401
402      ```swift
403      let results = realm.objects(Dog.self)
404      print("dogs.count: \(dogs?.count)") // => 0
405      let token = dogs.observe { changes in
406          switch changes {
407          case .initial(let dogs):
408              // Will print "dogs.count: 1"
409              print("dogs.count: \(dogs.count)")
410              break
411          case .update:
412              // Will not be hit in this example
413              break
414          case .error:
415              break
416          }
417      }
418      try! realm.write {
419          let dog = Dog()
420          dog.name = "Rex"
421          person.dogs.append(dog)
422      }
423      // end of run loop execution context
424      ```
425
426      You must retain the returned token for as long as you want updates to be sent to the block. To stop receiving
427      updates, call `invalidate()` on the token.
428
429      - warning: This method cannot be called during a write transaction, or when the containing Realm is read-only.
430
431      - parameter block: The block to be called whenever a change occurs.
432      - returns: A token which must be held for as long as you want updates to be delivered.
433      */
434     public func observe(_ block: @escaping (RealmCollectionChange<List>) -> Void) -> NotificationToken {
435         return _rlmArray.addNotificationBlock { _, change, error in
436             block(RealmCollectionChange.fromObjc(value: self, change: change, error: error))
437         }
438     }
439 }
440
441 extension List where Element: MinMaxType {
442     /**
443      Returns the minimum (lowest) value in the list, or `nil` if the list is empty.
444      */
445     public func min() -> Element? {
446         return _rlmArray.min(ofProperty: "self").map(dynamicBridgeCast)
447     }
448
449     /**
450      Returns the maximum (highest) value in the list, or `nil` if the list is empty.
451      */
452     public func max() -> Element? {
453         return _rlmArray.max(ofProperty: "self").map(dynamicBridgeCast)
454     }
455 }
456
457 extension List where Element: AddableType {
458     /**
459      Returns the sum of the values in the list.
460      */
461     public func sum() -> Element {
462         return sum(ofProperty: "self")
463     }
464
465     /**
466      Returns the average of the values in the list, or `nil` if the list is empty.
467      */
468     public func average() -> Double? {
469         return average(ofProperty: "self")
470     }
471 }
472
473 extension List: RealmCollection {
474     /// The type of the objects stored within the list.
475     public typealias ElementType = Element
476
477     // MARK: Sequence Support
478
479     /// Returns a `RLMIterator` that yields successive elements in the `List`.
480     public func makeIterator() -> RLMIterator<Element> {
481         return RLMIterator(collection: _rlmArray)
482     }
483
484     /**
485      Replace the given `subRange` of elements with `newElements`.
486
487      - parameter subrange:    The range of elements to be replaced.
488      - parameter newElements: The new elements to be inserted into the List.
489      */
490     public func replaceSubrange<C: Collection>(_ subrange: Range<Int>, with newElements: C)
491         where C.Iterator.Element == Element {
492             for _ in subrange.lowerBound..<subrange.upperBound {
493                 remove(at: subrange.lowerBound)
494             }
495             for x in newElements.reversed() {
496                 insert(x, at: subrange.lowerBound)
497             }
498     }
499
500     // This should be inferred, but Xcode 8.1 is unable to
501     /// :nodoc:
502     public typealias Indices = DefaultRandomAccessIndices<List>
503
504     /// The position of the first element in a non-empty collection.
505     /// Identical to endIndex in an empty collection.
506     public var startIndex: Int { return 0 }
507
508     /// The collection's "past the end" position.
509     /// endIndex is not a valid argument to subscript, and is always reachable from startIndex by
510     /// zero or more applications of successor().
511     public var endIndex: Int { return count }
512
513     public func index(after i: Int) -> Int { return i + 1 }
514     public func index(before i: Int) -> Int { return i - 1 }
515
516     /// :nodoc:
517     public func _observe(_ block: @escaping (RealmCollectionChange<AnyRealmCollection<Element>>) -> Void) -> NotificationToken {
518         let anyCollection = AnyRealmCollection(self)
519         return _rlmArray.addNotificationBlock { _, change, error in
520             block(RealmCollectionChange.fromObjc(value: anyCollection, change: change, error: error))
521         }
522     }
523 }
524
525 #if swift(>=4.0)
526 // MARK: - MutableCollection conformance, range replaceable collection emulation
527 extension List: MutableCollection {
528     public typealias SubSequence = RandomAccessSlice<List>
529
530     /**
531      Returns the objects at the given range (get), or replaces the objects at the
532      given range with new objects (set).
533
534      - warning: Objects may only be set during a write transaction.
535
536      - parameter index: The index of the object to retrieve or replace.
537      */
538     public subscript(bounds: Range<Int>) -> SubSequence {
539         get {
540             return SubSequence(base: self, bounds: bounds)
541         }
542         set {
543             replaceSubrange(bounds.lowerBound..<bounds.upperBound, with: newValue)
544         }
545     }
546
547     /**
548      Removes the specified number of objects from the beginning of the list. The
549      objects are not removed from the Realm that manages them.
550
551      - warning: This method may only be called during a write transaction.
552      */
553     public func removeFirst(_ number: Int = 1) {
554         let count = Int(_rlmArray.count)
555         guard number <= count else {
556             throwRealmException("It is not possible to remove more objects (\(number)) from a list"
557                 + " than it already contains (\(count)).")
558             return
559         }
560         for _ in 0..<number {
561             _rlmArray.removeObject(at: 0)
562         }
563     }
564
565     /**
566      Removes the specified number of objects from the end of the list. The objects
567      are not removed from the Realm that manages them.
568
569      - warning: This method may only be called during a write transaction.
570      */
571     public func removeLast(_ number: Int = 1) {
572         let count = Int(_rlmArray.count)
573         guard number <= count else {
574             throwRealmException("It is not possible to remove more objects (\(number)) from a list"
575                 + " than it already contains (\(count)).")
576             return
577         }
578         for _ in 0..<number {
579             _rlmArray.removeLastObject()
580         }
581     }
582
583     /**
584      Inserts the items in the given collection into the list at the given position.
585
586      - warning: This method may only be called during a write transaction.
587      */
588     public func insert<C: Collection>(contentsOf newElements: C, at i: Int) where C.Iterator.Element == Element {
589         var currentIndex = i
590         for item in newElements {
591             insert(item, at: currentIndex)
592             currentIndex += 1
593         }
594     }
595
596     /**
597      Removes objects from the list at the given range.
598
599      - warning: This method may only be called during a write transaction.
600      */
601     public func removeSubrange(_ bounds: Range<Int>) {
602         removeSubrange(bounds.lowerBound..<bounds.upperBound)
603     }
604
605     /// :nodoc:
606     public func removeSubrange(_ bounds: ClosedRange<Int>) {
607         removeSubrange(bounds.lowerBound...bounds.upperBound)
608     }
609
610     //// :nodoc:
611     public func removeSubrange(_ bounds: CountableRange<Int>) {
612         for _ in bounds {
613             remove(at: bounds.lowerBound)
614         }
615     }
616
617     /// :nodoc:
618     public func removeSubrange(_ bounds: CountableClosedRange<Int>) {
619         for _ in bounds {
620             remove(at: bounds.lowerBound)
621         }
622     }
623
624     /// :nodoc:
625     public func removeSubrange(_ bounds: DefaultRandomAccessIndices<List>) {
626         removeSubrange(bounds.startIndex..<bounds.endIndex)
627     }
628
629     /// :nodoc:
630     public func replaceSubrange<C: Collection>(_ subrange: ClosedRange<Int>, with newElements: C)
631         where C.Iterator.Element == Element {
632             removeSubrange(subrange)
633             insert(contentsOf: newElements, at: subrange.lowerBound)
634     }
635
636     /// :nodoc:
637     public func replaceSubrange<C: Collection>(_ subrange: CountableRange<Int>, with newElements: C)
638         where C.Iterator.Element == Element {
639             removeSubrange(subrange)
640             insert(contentsOf: newElements, at: subrange.lowerBound)
641     }
642
643     /// :nodoc:
644     public func replaceSubrange<C: Collection>(_ subrange: CountableClosedRange<Int>, with newElements: C)
645         where C.Iterator.Element == Element {
646             removeSubrange(subrange)
647             insert(contentsOf: newElements, at: subrange.lowerBound)
648     }
649
650     /// :nodoc:
651     public func replaceSubrange<C: Collection>(_ subrange: DefaultRandomAccessIndices<List>, with newElements: C)
652         where C.Iterator.Element == Element {
653             removeSubrange(subrange)
654             insert(contentsOf: newElements, at: subrange.startIndex)
655     }
656 }
657 #else
658 // MARK: - RangeReplaceableCollection support
659 extension List: RangeReplaceableCollection {
660     /**
661      Removes the last object in the list. The object is not removed from the Realm that manages it.
662
663      - warning: This method may only be called during a write transaction.
664      */
665     public func removeLast() {
666         guard _rlmArray.count > 0 else {
667             throwRealmException("It is not possible to remove an object from an empty list.")
668             return
669         }
670         _rlmArray.removeLastObject()
671     }
672
673 #if swift(>=3.1)
674     // These should not be necessary, but Swift 3.1's compiler fails to infer the `SubSequence`,
675     // and the standard library neglects to provide the default implementation of `subscript`
676     /// :nodoc:
677     public typealias SubSequence = RangeReplaceableRandomAccessSlice<List>
678
679     /// :nodoc:
680     public subscript(slice: Range<Int>) -> SubSequence {
681         return SubSequence(base: self, bounds: slice)
682     }
683 #endif
684 }
685 #endif
686
687 // MARK: - AssistedObjectiveCBridgeable
688
689 extension List: AssistedObjectiveCBridgeable {
690     internal static func bridging(from objectiveCValue: Any, with metadata: Any?) -> List {
691         guard let objectiveCValue = objectiveCValue as? RLMArray<AnyObject> else { preconditionFailure() }
692         return List(rlmArray: objectiveCValue)
693     }
694
695     internal var bridged: (objectiveCValue: Any, metadata: Any?) {
696         return (objectiveCValue: _rlmArray, metadata: nil)
697     }
698 }
699 // MARK: - Unavailable
700
701 extension List {
702     @available(*, unavailable, renamed: "remove(at:)")
703     public func remove(objectAtIndex: Int) { fatalError() }
704 }