added iOS source code
[wl-app.git] / iOS / Pods / RealmSwift / RealmSwift / Results.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
22 // MARK: MinMaxType
23
24 /**
25  Types of properties which can be used with the minimum and maximum value APIs.
26
27  - see: `min(ofProperty:)`, `max(ofProperty:)`
28  */
29 public protocol MinMaxType {}
30 extension NSNumber: MinMaxType {}
31 extension Double: MinMaxType {}
32 extension Float: MinMaxType {}
33 extension Int: MinMaxType {}
34 extension Int8: MinMaxType {}
35 extension Int16: MinMaxType {}
36 extension Int32: MinMaxType {}
37 extension Int64: MinMaxType {}
38 extension Date: MinMaxType {}
39 extension NSDate: MinMaxType {}
40
41 // MARK: AddableType
42
43 /**
44  Types of properties which can be used with the sum and average value APIs.
45
46  - see: `sum(ofProperty:)`, `average(ofProperty:)`
47  */
48 public protocol AddableType {
49     /// :nodoc:
50     init()
51 }
52 extension NSNumber: AddableType {}
53 extension Double: AddableType {}
54 extension Float: AddableType {}
55 extension Int: AddableType {}
56 extension Int8: AddableType {}
57 extension Int16: AddableType {}
58 extension Int32: AddableType {}
59 extension Int64: AddableType {}
60
61 /**
62  `Results` is an auto-updating container type in Realm returned from object queries.
63
64  `Results` can be queried with the same predicates as `List<Element>`, and you can
65  chain queries to further filter query results.
66
67  `Results` always reflect the current state of the Realm on the current thread, including during write transactions on
68  the current thread. The one exception to this is when using `for...in` enumeration, which will always enumerate over
69  the objects which matched the query when the enumeration is begun, even if some of them are deleted or modified to be
70  excluded by the filter during the enumeration.
71
72  `Results` are lazily evaluated the first time they are accessed; they only run queries when the result of the query is
73  requested. This means that chaining several temporary `Results` to sort and filter your data does not perform any
74  unnecessary work processing the intermediate state.
75
76  Once the results have been evaluated or a notification block has been added, the results are eagerly kept up-to-date,
77  with the work done to keep them up-to-date done on a background thread whenever possible.
78
79  Results instances cannot be directly instantiated.
80  */
81 public final class Results<Element: RealmCollectionValue>: NSObject, NSFastEnumeration {
82
83     internal let rlmResults: RLMResults<AnyObject>
84
85     /// A human-readable description of the objects represented by the results.
86     public override var description: String {
87         return RLMDescriptionWithMaxDepth("Results", rlmResults, RLMDescriptionMaxDepth)
88     }
89
90     // MARK: Fast Enumeration
91
92     /// :nodoc:
93     public func countByEnumerating(with state: UnsafeMutablePointer<NSFastEnumerationState>,
94                                    objects buffer: AutoreleasingUnsafeMutablePointer<AnyObject?>,
95                                    count len: Int) -> Int {
96         return Int(rlmResults.countByEnumerating(with: state, objects: buffer, count: UInt(len)))
97     }
98
99     /// The type of the objects described by the results.
100     public typealias ElementType = Element
101
102     // MARK: Properties
103
104     /// The Realm which manages this results. Note that this property will never return `nil`.
105     public var realm: Realm? { return Realm(rlmResults.realm) }
106
107     /**
108      Indicates if the results are no longer valid.
109
110      The results becomes invalid if `invalidate()` is called on the containing `realm`. An invalidated results can be
111      accessed, but will always be empty.
112      */
113     public var isInvalidated: Bool { return rlmResults.isInvalidated }
114
115     /// The number of objects in the results.
116     public var count: Int { return Int(rlmResults.count) }
117
118     // MARK: Initializers
119
120     internal init(_ rlmResults: RLMResults<AnyObject>) {
121         self.rlmResults = rlmResults
122     }
123
124     // MARK: Index Retrieval
125
126     /**
127      Returns the index of the given object in the results, or `nil` if the object is not present.
128      */
129     public func index(of object: Element) -> Int? {
130         return notFoundToNil(index: rlmResults.index(of: object as AnyObject))
131     }
132
133     /**
134      Returns the index of the first object matching the predicate, or `nil` if no objects match.
135
136      - parameter predicate: The predicate with which to filter the objects.
137      */
138     public func index(matching predicate: NSPredicate) -> Int? {
139         return notFoundToNil(index: rlmResults.indexOfObject(with: predicate))
140     }
141
142     /**
143      Returns the index of the first object matching the predicate, or `nil` if no objects match.
144
145      - parameter predicateFormat: A predicate format string, optionally followed by a variable number of arguments.
146      */
147     public func index(matching predicateFormat: String, _ args: Any...) -> Int? {
148         return notFoundToNil(index: rlmResults.indexOfObject(with: NSPredicate(format: predicateFormat,
149                                                                                argumentArray: unwrapOptionals(in: args))))
150     }
151
152     // MARK: Object Retrieval
153
154     /**
155      Returns the object at the given `index`.
156
157      - parameter index: The index.
158      */
159     public subscript(position: Int) -> Element {
160         throwForNegativeIndex(position)
161         return dynamicBridgeCast(fromObjectiveC: rlmResults.object(at: UInt(position)))
162     }
163
164     /// Returns the first object in the results, or `nil` if the results are empty.
165     public var first: Element? { return rlmResults.firstObject().map(dynamicBridgeCast) }
166
167     /// Returns the last object in the results, or `nil` if the results are empty.
168     public var last: Element? { return rlmResults.lastObject().map(dynamicBridgeCast) }
169
170     // MARK: KVC
171
172     /**
173      Returns an `Array` containing the results of invoking `valueForKey(_:)` with `key` on each of the results.
174
175      - parameter key: The name of the property whose values are desired.
176      */
177     public override func value(forKey key: String) -> Any? {
178         return value(forKeyPath: key)
179     }
180
181     /**
182      Returns an `Array` containing the results of invoking `valueForKeyPath(_:)` with `keyPath` on each of the results.
183
184      - parameter keyPath: The key path to the property whose values are desired.
185      */
186     public override func value(forKeyPath keyPath: String) -> Any? {
187         return rlmResults.value(forKeyPath: keyPath)
188     }
189
190     /**
191      Invokes `setValue(_:forKey:)` on each of the objects represented by the results using the specified `value` and
192      `key`.
193
194      - warning: This method may only be called during a write transaction.
195
196      - parameter value: The object value.
197      - parameter key:   The name of the property whose value should be set on each object.
198      */
199     public override func setValue(_ value: Any?, forKey key: String) {
200         return rlmResults.setValue(value, forKeyPath: key)
201     }
202
203     // MARK: Filtering
204
205     /**
206      Returns a `Results` containing all objects matching the given predicate in the collection.
207
208      - parameter predicateFormat: A predicate format string, optionally followed by a variable number of arguments.
209      */
210     public func filter(_ predicateFormat: String, _ args: Any...) -> Results<Element> {
211         return Results<Element>(rlmResults.objects(with: NSPredicate(format: predicateFormat,
212                                                                      argumentArray: unwrapOptionals(in: args))))
213     }
214
215     /**
216      Returns a `Results` containing all objects matching the given predicate in the collection.
217
218      - parameter predicate: The predicate with which to filter the objects.
219      */
220     public func filter(_ predicate: NSPredicate) -> Results<Element> {
221         return Results<Element>(rlmResults.objects(with: predicate))
222     }
223
224     // MARK: Sorting
225
226     /**
227      Returns a `Results` containing the objects represented by the results, but sorted.
228
229      Objects are sorted based on the values of the given key path. For example, to sort a collection of `Student`s from
230      youngest to oldest based on their `age` property, you might call
231      `students.sorted(byKeyPath: "age", ascending: true)`.
232
233      - warning: Collections may only be sorted by properties of boolean, `Date`, `NSDate`, single and double-precision
234                 floating point, integer, and string types.
235
236      - parameter keyPath:   The key path to sort by.
237      - parameter ascending: The direction to sort in.
238      */
239     public func sorted(byKeyPath keyPath: String, ascending: Bool = true) -> Results<Element> {
240         return sorted(by: [SortDescriptor(keyPath: keyPath, ascending: ascending)])
241     }
242
243     /**
244      Returns a `Results` containing the objects represented by the results, but sorted.
245
246      - warning: Collections may only be sorted by properties of boolean, `Date`, `NSDate`, single and double-precision
247                 floating point, integer, and string types.
248
249      - see: `sorted(byKeyPath:ascending:)`
250
251      - parameter sortDescriptors: A sequence of `SortDescriptor`s to sort by.
252      */
253     public func sorted<S: Sequence>(by sortDescriptors: S) -> Results<Element>
254         where S.Iterator.Element == SortDescriptor {
255             return Results<Element>(rlmResults.sortedResults(using: sortDescriptors.map { $0.rlmSortDescriptorValue }))
256     }
257
258     /**
259      Returns a `Results` containing distinct objects based on the specified key paths
260      
261      - parameter keyPaths:  The key paths used produce distinct results
262      */
263     public func distinct<S: Sequence>(by keyPaths: S) -> Results<Element>
264         where S.Iterator.Element == String {
265             return Results<Element>(rlmResults.distinctResults(usingKeyPaths: Array(keyPaths)))
266     }
267
268     // MARK: Aggregate Operations
269
270     /**
271      Returns the minimum (lowest) value of the given property among all the results, or `nil` if the results are empty.
272
273      - warning: Only a property whose type conforms to the `MinMaxType` protocol can be specified.
274
275      - parameter property: The name of a property whose minimum value is desired.
276      */
277     public func min<T: MinMaxType>(ofProperty property: String) -> T? {
278         return rlmResults.min(ofProperty: property).map(dynamicBridgeCast)
279     }
280
281     /**
282      Returns the maximum (highest) value of the given property among all the results, or `nil` if the results are empty.
283
284      - warning: Only a property whose type conforms to the `MinMaxType` protocol can be specified.
285
286      - parameter property: The name of a property whose minimum value is desired.
287      */
288     public func max<T: MinMaxType>(ofProperty property: String) -> T? {
289         return rlmResults.max(ofProperty: property).map(dynamicBridgeCast)
290     }
291
292     /**
293      Returns the sum of the values of a given property over all the results.
294
295      - warning: Only a property whose type conforms to the `AddableType` protocol can be specified.
296
297      - parameter property: The name of a property whose values should be summed.
298      */
299     public func sum<T: AddableType>(ofProperty property: String) -> T {
300         return dynamicBridgeCast(fromObjectiveC: rlmResults.sum(ofProperty: property))
301     }
302
303     /**
304      Returns the average value of a given property over all the results, or `nil` if the results are empty.
305
306      - warning: Only the name of a property whose type conforms to the `AddableType` protocol can be specified.
307
308      - parameter property: The name of a property whose average value should be calculated.
309      */
310     public func average<T: AddableType>(ofProperty property: String) -> T? {
311         return rlmResults.average(ofProperty: property).map(dynamicBridgeCast)
312     }
313
314     // MARK: Notifications
315
316     /**
317      Registers a block to be called each time the collection changes.
318
319      The block will be asynchronously called with the initial results, and then called again after each write
320      transaction which changes either any of the objects in the collection, or which objects are in the collection.
321
322      The `change` parameter that is passed to the block reports, in the form of indices within the collection, which of
323      the objects were added, removed, or modified during each write transaction. See the `RealmCollectionChange`
324      documentation for more information on the change information supplied and an example of how to use it to update a
325      `UITableView`.
326
327      At the time when the block is called, the collection will be fully evaluated and up-to-date, and as long as you do
328      not perform a write transaction on the same thread or explicitly call `realm.refresh()`, accessing it will never
329      perform blocking work.
330
331      Notifications are delivered via the standard run loop, and so can't be delivered while the run loop is blocked by
332      other activity. When notifications can't be delivered instantly, multiple notifications may be coalesced into a
333      single notification. This can include the notification with the initial collection.
334
335      For example, the following code performs a write transaction immediately after adding the notification block, so
336      there is no opportunity for the initial notification to be delivered first. As a result, the initial notification
337      will reflect the state of the Realm after the write transaction.
338
339      ```swift
340      let results = realm.objects(Dog.self)
341      print("dogs.count: \(dogs?.count)") // => 0
342      let token = dogs.observe { changes in
343          switch changes {
344          case .initial(let dogs):
345              // Will print "dogs.count: 1"
346              print("dogs.count: \(dogs.count)")
347              break
348          case .update:
349              // Will not be hit in this example
350              break
351          case .error:
352              break
353          }
354      }
355      try! realm.write {
356          let dog = Dog()
357          dog.name = "Rex"
358          person.dogs.append(dog)
359      }
360      // end of run loop execution context
361      ```
362
363      You must retain the returned token for as long as you want updates to be sent to the block. To stop receiving
364      updates, call `invalidate()` on the token.
365
366      - warning: This method cannot be called during a write transaction, or when the containing Realm is read-only.
367
368      - parameter block: The block to be called whenever a change occurs.
369      - returns: A token which must be held for as long as you want updates to be delivered.
370      */
371     public func observe(_ block: @escaping (RealmCollectionChange<Results>) -> Void) -> NotificationToken {
372         return rlmResults.addNotificationBlock { _, change, error in
373             block(RealmCollectionChange.fromObjc(value: self, change: change, error: error))
374         }
375     }
376 }
377
378 extension Results: RealmCollection {
379     // MARK: Sequence Support
380
381     /// Returns a `RLMIterator` that yields successive elements in the results.
382     public func makeIterator() -> RLMIterator<Element> {
383         return RLMIterator(collection: rlmResults)
384     }
385
386     // MARK: Collection Support
387
388     /// The position of the first element in a non-empty collection.
389     /// Identical to endIndex in an empty collection.
390     public var startIndex: Int { return 0 }
391
392     /// The collection's "past the end" position.
393     /// endIndex is not a valid argument to subscript, and is always reachable from startIndex by
394     /// zero or more applications of successor().
395     public var endIndex: Int { return count }
396
397     public func index(after i: Int) -> Int { return i + 1 }
398     public func index(before i: Int) -> Int { return i - 1 }
399
400     /// :nodoc:
401     public func _observe(_ block: @escaping (RealmCollectionChange<AnyRealmCollection<Element>>) -> Void) ->
402         NotificationToken {
403         let anyCollection = AnyRealmCollection(self)
404         return rlmResults.addNotificationBlock { _, change, error in
405             block(RealmCollectionChange.fromObjc(value: anyCollection, change: change, error: error))
406         }
407     }
408 }
409
410 // MARK: AssistedObjectiveCBridgeable
411
412 extension Results: AssistedObjectiveCBridgeable {
413     static func bridging(from objectiveCValue: Any, with metadata: Any?) -> Results {
414         return Results(objectiveCValue as! RLMResults)
415     }
416
417     var bridged: (objectiveCValue: Any, metadata: Any?) {
418         return (objectiveCValue: rlmResults, metadata: nil)
419     }
420 }