added iOS source code
[wl-app.git] / iOS / Pods / RealmSwift / RealmSwift / List.swift
diff --git a/iOS/Pods/RealmSwift/RealmSwift/List.swift b/iOS/Pods/RealmSwift/RealmSwift/List.swift
new file mode 100644 (file)
index 0000000..61f522a
--- /dev/null
@@ -0,0 +1,704 @@
+////////////////////////////////////////////////////////////////////////////
+//
+// 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
+
+/// :nodoc:
+/// Internal class. Do not use directly.
+public class ListBase: RLMListBase {
+    // Printable requires a description property defined in Swift (and not obj-c),
+    // and it has to be defined as override, which can't be done in a
+    // generic class.
+    /// Returns a human-readable description of the objects contained in the List.
+    @objc public override var description: String {
+        return descriptionWithMaxDepth(RLMDescriptionMaxDepth)
+    }
+
+    @objc private func descriptionWithMaxDepth(_ depth: UInt) -> String {
+        return RLMDescriptionWithMaxDepth("List", _rlmArray, depth)
+    }
+
+    /// Returns the number of objects in this List.
+    public var count: Int { return Int(_rlmArray.count) }
+}
+
+/**
+ `List` is the container type in Realm used to define to-many relationships.
+
+ Like Swift's `Array`, `List` is a generic type that is parameterized on the type of `Object` it stores.
+
+ Unlike Swift's native collections, `List`s are reference types, and are only immutable if the Realm that manages them
+ is opened as read-only.
+
+ Lists can be filtered and sorted with the same predicates as `Results<Element>`.
+
+ Properties of `List` type defined on `Object` subclasses must be declared as `let` and cannot be `dynamic`.
+ */
+public final class List<Element: RealmCollectionValue>: ListBase {
+
+    // MARK: Properties
+
+    /// The Realm which manages the list, or `nil` if the list is unmanaged.
+    public var realm: Realm? {
+        return _rlmArray.realm.map { Realm($0) }
+    }
+
+    /// Indicates if the list can no longer be accessed.
+    public var isInvalidated: Bool { return _rlmArray.isInvalidated }
+
+    // MARK: Initializers
+
+    /// Creates a `List` that holds Realm model objects of type `Element`.
+    public override init() {
+        super.init(array: Element._rlmArray())
+    }
+
+    internal init(rlmArray: RLMArray<AnyObject>) {
+        super.init(array: rlmArray)
+    }
+
+    // MARK: Index Retrieval
+
+    /**
+     Returns the index of an object in the list, or `nil` if the object is not present.
+
+     - parameter object: An object to find.
+     */
+    public func index(of object: Element) -> Int? {
+        return notFoundToNil(index: _rlmArray.index(of: dynamicBridgeCast(fromSwift: object) as AnyObject))
+    }
+
+    /**
+     Returns the index of the first object in the list matching the predicate, or `nil` if no objects match.
+
+     - parameter predicate: The predicate with which to filter the objects.
+    */
+    public func index(matching predicate: NSPredicate) -> Int? {
+        return notFoundToNil(index: _rlmArray.indexOfObject(with: predicate))
+    }
+
+    /**
+     Returns the index of the first object in the list matching the predicate, or `nil` if no objects match.
+
+     - parameter predicateFormat: A predicate format string, optionally followed by a variable number of arguments.
+    */
+    public func index(matching predicateFormat: String, _ args: Any...) -> Int? {
+        return index(matching: NSPredicate(format: predicateFormat, argumentArray: unwrapOptionals(in: args)))
+    }
+
+    // MARK: Object Retrieval
+
+    /**
+     Returns the object at the given index (get), or replaces the object at the given index (set).
+
+     - warning: You can only set an object during a write transaction.
+
+     - parameter index: The index of the object to retrieve or replace.
+     */
+    public subscript(position: Int) -> Element {
+        get {
+            throwForNegativeIndex(position)
+            return dynamicBridgeCast(fromObjectiveC: _rlmArray.object(at: UInt(position)))
+        }
+        set {
+            throwForNegativeIndex(position)
+            _rlmArray.replaceObject(at: UInt(position), with: dynamicBridgeCast(fromSwift: newValue) as AnyObject)
+        }
+    }
+
+    /// Returns the first object in the list, or `nil` if the list is empty.
+    public var first: Element? { return _rlmArray.firstObject().map(dynamicBridgeCast) }
+
+    /// Returns the last object in the list, or `nil` if the list is empty.
+    public var last: Element? { return _rlmArray.lastObject().map(dynamicBridgeCast) }
+
+    // MARK: KVC
+
+    /**
+     Returns an `Array` containing the results of invoking `valueForKey(_:)` using `key` on each of the collection's
+     objects.
+     */
+    @nonobjc public func value(forKey key: String) -> [AnyObject] {
+        return _rlmArray.value(forKeyPath: key)! as! [AnyObject]
+    }
+
+    /**
+     Returns an `Array` containing the results of invoking `valueForKeyPath(_:)` using `keyPath` on each of the
+     collection's objects.
+
+     - parameter keyPath: The key path to the property whose values are desired.
+     */
+    @nonobjc public func value(forKeyPath keyPath: String) -> [AnyObject] {
+        return _rlmArray.value(forKeyPath: keyPath) as! [AnyObject]
+    }
+
+    /**
+     Invokes `setValue(_:forKey:)` on each of the collection's objects using the specified `value` and `key`.
+
+     - warning: This method can only be called during a write transaction.
+
+     - parameter value: The object value.
+     - parameter key:   The name of the property whose value should be set on each object.
+    */
+    public override func setValue(_ value: Any?, forKey key: String) {
+        return _rlmArray.setValue(value, forKeyPath: key)
+    }
+
+    // MARK: Filtering
+
+    /**
+     Returns a `Results` containing all objects matching the given predicate in the list.
+
+     - parameter predicateFormat: A predicate format string, optionally followed by a variable number of arguments.
+    */
+    public func filter(_ predicateFormat: String, _ args: Any...) -> Results<Element> {
+        return Results<Element>(_rlmArray.objects(with: NSPredicate(format: predicateFormat,
+                                                              argumentArray: unwrapOptionals(in: args))))
+    }
+
+    /**
+     Returns a `Results` containing all objects matching the given predicate in the list.
+
+     - parameter predicate: The predicate with which to filter the objects.
+     */
+    public func filter(_ predicate: NSPredicate) -> Results<Element> {
+        return Results<Element>(_rlmArray.objects(with: predicate))
+    }
+
+    // MARK: Sorting
+
+    /**
+     Returns a `Results` containing the objects in the list, but sorted.
+
+     Objects are sorted based on the values of the given key path. For example, to sort a list of `Student`s from
+     youngest to oldest based on their `age` property, you might call
+     `students.sorted(byKeyPath: "age", ascending: true)`.
+
+     - warning: Lists may only be sorted by properties of boolean, `Date`, `NSDate`, single and double-precision
+                floating point, integer, and string types.
+
+     - parameter keyPath:  The key path to sort by.
+     - parameter ascending: The direction to sort in.
+     */
+    public func sorted(byKeyPath keyPath: String, ascending: Bool = true) -> Results<Element> {
+        return sorted(by: [SortDescriptor(keyPath: keyPath, ascending: ascending)])
+    }
+
+    /**
+     Returns a `Results` containing the objects in the list, but sorted.
+
+     - warning: Lists may only be sorted by properties of boolean, `Date`, `NSDate`, single and double-precision
+                floating point, integer, and string types.
+
+     - see: `sorted(byKeyPath:ascending:)`
+    */
+    public func sorted<S: Sequence>(by sortDescriptors: S) -> Results<Element>
+        where S.Iterator.Element == SortDescriptor {
+            return Results<Element>(_rlmArray.sortedResults(using: sortDescriptors.map { $0.rlmSortDescriptorValue }))
+    }
+
+    // MARK: Aggregate Operations
+
+    /**
+     Returns the minimum (lowest) value of the given property among all the objects in the list, or `nil` if the list is
+     empty.
+
+     - warning: Only a property whose type conforms to the `MinMaxType` protocol can be specified.
+
+     - parameter property: The name of a property whose minimum value is desired.
+     */
+    public func min<T: MinMaxType>(ofProperty property: String) -> T? {
+        return _rlmArray.min(ofProperty: property).map(dynamicBridgeCast)
+    }
+
+    /**
+     Returns the maximum (highest) value of the given property among all the objects in the list, or `nil` if the list
+     is empty.
+
+     - warning: Only a property whose type conforms to the `MinMaxType` protocol can be specified.
+
+     - parameter property: The name of a property whose maximum value is desired.
+     */
+    public func max<T: MinMaxType>(ofProperty property: String) -> T? {
+        return _rlmArray.max(ofProperty: property).map(dynamicBridgeCast)
+    }
+
+    /**
+     Returns the sum of the values of a given property over all the objects in the list.
+
+     - warning: Only a property whose type conforms to the `AddableType` protocol can be specified.
+
+     - parameter property: The name of a property whose values should be summed.
+     */
+    public func sum<T: AddableType>(ofProperty property: String) -> T {
+        return dynamicBridgeCast(fromObjectiveC: _rlmArray.sum(ofProperty: property))
+    }
+
+    /**
+     Returns the average value of a given property over all the objects in the list, or `nil` if the list is empty.
+
+     - warning: Only a property whose type conforms to the `AddableType` protocol can be specified.
+
+     - parameter property: The name of a property whose average value should be calculated.
+     */
+    public func average(ofProperty property: String) -> Double? {
+        return _rlmArray.average(ofProperty: property).map(dynamicBridgeCast)
+    }
+
+    // MARK: Mutation
+
+    /**
+     Appends the given object to the end of the list.
+
+     If the object is managed by a different Realm than the receiver, a copy is made and added to the Realm managing
+     the receiver.
+
+     - warning: This method may only be called during a write transaction.
+
+     - parameter object: An object.
+     */
+    public func append(_ object: Element) {
+        _rlmArray.add(dynamicBridgeCast(fromSwift: object) as AnyObject)
+    }
+
+    /**
+     Appends the objects in the given sequence to the end of the list.
+
+     - warning: This method may only be called during a write transaction.
+    */
+    public func append<S: Sequence>(objectsIn objects: S) where S.Iterator.Element == Element {
+        for obj in objects {
+            _rlmArray.add(dynamicBridgeCast(fromSwift: obj) as AnyObject)
+        }
+    }
+
+    /**
+     Inserts an object at the given index.
+
+     - warning: This method may only be called during a write transaction.
+
+     - warning: This method will throw an exception if called with an invalid index.
+
+     - parameter object: An object.
+     - parameter index:  The index at which to insert the object.
+     */
+    public func insert(_ object: Element, at index: Int) {
+        throwForNegativeIndex(index)
+        _rlmArray.insert(dynamicBridgeCast(fromSwift: object) as AnyObject, at: UInt(index))
+    }
+
+    /**
+     Removes an object at the given index. The object is not removed from the Realm that manages it.
+
+     - warning: This method may only be called during a write transaction.
+
+     - warning: This method will throw an exception if called with an invalid index.
+
+     - parameter index: The index at which to remove the object.
+     */
+    public func remove(at index: Int) {
+        throwForNegativeIndex(index)
+        _rlmArray.removeObject(at: UInt(index))
+    }
+
+    /**
+     Removes all objects from the list. The objects are not removed from the Realm that manages them.
+
+     - warning: This method may only be called during a write transaction.
+     */
+    public func removeAll() {
+        _rlmArray.removeAllObjects()
+    }
+
+    /**
+     Replaces an object at the given index with a new object.
+
+     - warning: This method may only be called during a write transaction.
+
+     - warning: This method will throw an exception if called with an invalid index.
+
+     - parameter index:  The index of the object to be replaced.
+     - parameter object: An object.
+     */
+    public func replace(index: Int, object: Element) {
+        throwForNegativeIndex(index)
+        _rlmArray.replaceObject(at: UInt(index), with: dynamicBridgeCast(fromSwift: object) as AnyObject)
+    }
+
+    /**
+     Moves the object at the given source index to the given destination index.
+
+     - warning: This method may only be called during a write transaction.
+
+     - warning: This method will throw an exception if called with invalid indices.
+
+     - parameter from:  The index of the object to be moved.
+     - parameter to:    index to which the object at `from` should be moved.
+     */
+    public func move(from: Int, to: Int) {
+        throwForNegativeIndex(from)
+        throwForNegativeIndex(to)
+        _rlmArray.moveObject(at: UInt(from), to: UInt(to))
+    }
+
+    /**
+     Exchanges the objects in the list at given indices.
+
+     - warning: This method may only be called during a write transaction.
+
+     - warning: This method will throw an exception if called with invalid indices.
+
+     - parameter index1: The index of the object which should replace the object at index `index2`.
+     - parameter index2: The index of the object which should replace the object at index `index1`.
+     */
+    public func swapAt(_ index1: Int, _ index2: Int) {
+        throwForNegativeIndex(index1, parameterName: "index1")
+        throwForNegativeIndex(index2, parameterName: "index2")
+        _rlmArray.exchangeObject(at: UInt(index1), withObjectAt: UInt(index2))
+    }
+
+    // MARK: Notifications
+
+    /**
+     Registers a block to be called each time the collection changes.
+
+     The block will be asynchronously called with the initial results, and then called again after each write
+     transaction which changes either any of the objects in the collection, or which objects are in the collection.
+
+     The `change` parameter that is passed to the block reports, in the form of indices within the collection, which of
+     the objects were added, removed, or modified during each write transaction. See the `RealmCollectionChange`
+     documentation for more information on the change information supplied and an example of how to use it to update a
+     `UITableView`.
+
+     At the time when the block is called, the collection will be fully evaluated and up-to-date, and as long as you do
+     not perform a write transaction on the same thread or explicitly call `realm.refresh()`, accessing it will never
+     perform blocking work.
+
+     Notifications are delivered via the standard run loop, and so can't be delivered while the run loop is blocked by
+     other activity. When notifications can't be delivered instantly, multiple notifications may be coalesced into a
+     single notification. This can include the notification with the initial collection.
+
+     For example, the following code performs a write transaction immediately after adding the notification block, so
+     there is no opportunity for the initial notification to be delivered first. As a result, the initial notification
+     will reflect the state of the Realm after the write transaction.
+
+     ```swift
+     let results = realm.objects(Dog.self)
+     print("dogs.count: \(dogs?.count)") // => 0
+     let token = dogs.observe { changes in
+         switch changes {
+         case .initial(let dogs):
+             // Will print "dogs.count: 1"
+             print("dogs.count: \(dogs.count)")
+             break
+         case .update:
+             // Will not be hit in this example
+             break
+         case .error:
+             break
+         }
+     }
+     try! realm.write {
+         let dog = Dog()
+         dog.name = "Rex"
+         person.dogs.append(dog)
+     }
+     // end of run loop execution context
+     ```
+
+     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.
+
+     - warning: This method cannot be called during a write transaction, or when the containing Realm is read-only.
+
+     - parameter block: The block to be called whenever a change occurs.
+     - returns: A token which must be held for as long as you want updates to be delivered.
+     */
+    public func observe(_ block: @escaping (RealmCollectionChange<List>) -> Void) -> NotificationToken {
+        return _rlmArray.addNotificationBlock { _, change, error in
+            block(RealmCollectionChange.fromObjc(value: self, change: change, error: error))
+        }
+    }
+}
+
+extension List where Element: MinMaxType {
+    /**
+     Returns the minimum (lowest) value in the list, or `nil` if the list is empty.
+     */
+    public func min() -> Element? {
+        return _rlmArray.min(ofProperty: "self").map(dynamicBridgeCast)
+    }
+
+    /**
+     Returns the maximum (highest) value in the list, or `nil` if the list is empty.
+     */
+    public func max() -> Element? {
+        return _rlmArray.max(ofProperty: "self").map(dynamicBridgeCast)
+    }
+}
+
+extension List where Element: AddableType {
+    /**
+     Returns the sum of the values in the list.
+     */
+    public func sum() -> Element {
+        return sum(ofProperty: "self")
+    }
+
+    /**
+     Returns the average of the values in the list, or `nil` if the list is empty.
+     */
+    public func average() -> Double? {
+        return average(ofProperty: "self")
+    }
+}
+
+extension List: RealmCollection {
+    /// The type of the objects stored within the list.
+    public typealias ElementType = Element
+
+    // MARK: Sequence Support
+
+    /// Returns a `RLMIterator` that yields successive elements in the `List`.
+    public func makeIterator() -> RLMIterator<Element> {
+        return RLMIterator(collection: _rlmArray)
+    }
+
+    /**
+     Replace the given `subRange` of elements with `newElements`.
+
+     - parameter subrange:    The range of elements to be replaced.
+     - parameter newElements: The new elements to be inserted into the List.
+     */
+    public func replaceSubrange<C: Collection>(_ subrange: Range<Int>, with newElements: C)
+        where C.Iterator.Element == Element {
+            for _ in subrange.lowerBound..<subrange.upperBound {
+                remove(at: subrange.lowerBound)
+            }
+            for x in newElements.reversed() {
+                insert(x, at: subrange.lowerBound)
+            }
+    }
+
+    // This should be inferred, but Xcode 8.1 is unable to
+    /// :nodoc:
+    public typealias Indices = DefaultRandomAccessIndices<List>
+
+    /// The position of the first element in a non-empty collection.
+    /// Identical to endIndex in an empty collection.
+    public var startIndex: Int { return 0 }
+
+    /// The collection's "past the end" position.
+    /// endIndex is not a valid argument to subscript, and is always reachable from startIndex by
+    /// zero or more applications of successor().
+    public var endIndex: Int { return count }
+
+    public func index(after i: Int) -> Int { return i + 1 }
+    public func index(before i: Int) -> Int { return i - 1 }
+
+    /// :nodoc:
+    public func _observe(_ block: @escaping (RealmCollectionChange<AnyRealmCollection<Element>>) -> Void) -> NotificationToken {
+        let anyCollection = AnyRealmCollection(self)
+        return _rlmArray.addNotificationBlock { _, change, error in
+            block(RealmCollectionChange.fromObjc(value: anyCollection, change: change, error: error))
+        }
+    }
+}
+
+#if swift(>=4.0)
+// MARK: - MutableCollection conformance, range replaceable collection emulation
+extension List: MutableCollection {
+    public typealias SubSequence = RandomAccessSlice<List>
+
+    /**
+     Returns the objects at the given range (get), or replaces the objects at the
+     given range with new objects (set).
+
+     - warning: Objects may only be set during a write transaction.
+
+     - parameter index: The index of the object to retrieve or replace.
+     */
+    public subscript(bounds: Range<Int>) -> SubSequence {
+        get {
+            return SubSequence(base: self, bounds: bounds)
+        }
+        set {
+            replaceSubrange(bounds.lowerBound..<bounds.upperBound, with: newValue)
+        }
+    }
+
+    /**
+     Removes the specified number of objects from the beginning of the list. The
+     objects are not removed from the Realm that manages them.
+
+     - warning: This method may only be called during a write transaction.
+     */
+    public func removeFirst(_ number: Int = 1) {
+        let count = Int(_rlmArray.count)
+        guard number <= count else {
+            throwRealmException("It is not possible to remove more objects (\(number)) from a list"
+                + " than it already contains (\(count)).")
+            return
+        }
+        for _ in 0..<number {
+            _rlmArray.removeObject(at: 0)
+        }
+    }
+
+    /**
+     Removes the specified number of objects from the end of the list. The objects
+     are not removed from the Realm that manages them.
+
+     - warning: This method may only be called during a write transaction.
+     */
+    public func removeLast(_ number: Int = 1) {
+        let count = Int(_rlmArray.count)
+        guard number <= count else {
+            throwRealmException("It is not possible to remove more objects (\(number)) from a list"
+                + " than it already contains (\(count)).")
+            return
+        }
+        for _ in 0..<number {
+            _rlmArray.removeLastObject()
+        }
+    }
+
+    /**
+     Inserts the items in the given collection into the list at the given position.
+
+     - warning: This method may only be called during a write transaction.
+     */
+    public func insert<C: Collection>(contentsOf newElements: C, at i: Int) where C.Iterator.Element == Element {
+        var currentIndex = i
+        for item in newElements {
+            insert(item, at: currentIndex)
+            currentIndex += 1
+        }
+    }
+
+    /**
+     Removes objects from the list at the given range.
+
+     - warning: This method may only be called during a write transaction.
+     */
+    public func removeSubrange(_ bounds: Range<Int>) {
+        removeSubrange(bounds.lowerBound..<bounds.upperBound)
+    }
+
+    /// :nodoc:
+    public func removeSubrange(_ bounds: ClosedRange<Int>) {
+        removeSubrange(bounds.lowerBound...bounds.upperBound)
+    }
+
+    //// :nodoc:
+    public func removeSubrange(_ bounds: CountableRange<Int>) {
+        for _ in bounds {
+            remove(at: bounds.lowerBound)
+        }
+    }
+
+    /// :nodoc:
+    public func removeSubrange(_ bounds: CountableClosedRange<Int>) {
+        for _ in bounds {
+            remove(at: bounds.lowerBound)
+        }
+    }
+
+    /// :nodoc:
+    public func removeSubrange(_ bounds: DefaultRandomAccessIndices<List>) {
+        removeSubrange(bounds.startIndex..<bounds.endIndex)
+    }
+
+    /// :nodoc:
+    public func replaceSubrange<C: Collection>(_ subrange: ClosedRange<Int>, with newElements: C)
+        where C.Iterator.Element == Element {
+            removeSubrange(subrange)
+            insert(contentsOf: newElements, at: subrange.lowerBound)
+    }
+
+    /// :nodoc:
+    public func replaceSubrange<C: Collection>(_ subrange: CountableRange<Int>, with newElements: C)
+        where C.Iterator.Element == Element {
+            removeSubrange(subrange)
+            insert(contentsOf: newElements, at: subrange.lowerBound)
+    }
+
+    /// :nodoc:
+    public func replaceSubrange<C: Collection>(_ subrange: CountableClosedRange<Int>, with newElements: C)
+        where C.Iterator.Element == Element {
+            removeSubrange(subrange)
+            insert(contentsOf: newElements, at: subrange.lowerBound)
+    }
+
+    /// :nodoc:
+    public func replaceSubrange<C: Collection>(_ subrange: DefaultRandomAccessIndices<List>, with newElements: C)
+        where C.Iterator.Element == Element {
+            removeSubrange(subrange)
+            insert(contentsOf: newElements, at: subrange.startIndex)
+    }
+}
+#else
+// MARK: - RangeReplaceableCollection support
+extension List: RangeReplaceableCollection {
+    /**
+     Removes the last object in the list. The object is not removed from the Realm that manages it.
+
+     - warning: This method may only be called during a write transaction.
+     */
+    public func removeLast() {
+        guard _rlmArray.count > 0 else {
+            throwRealmException("It is not possible to remove an object from an empty list.")
+            return
+        }
+        _rlmArray.removeLastObject()
+    }
+
+#if swift(>=3.1)
+    // These should not be necessary, but Swift 3.1's compiler fails to infer the `SubSequence`,
+    // and the standard library neglects to provide the default implementation of `subscript`
+    /// :nodoc:
+    public typealias SubSequence = RangeReplaceableRandomAccessSlice<List>
+
+    /// :nodoc:
+    public subscript(slice: Range<Int>) -> SubSequence {
+        return SubSequence(base: self, bounds: slice)
+    }
+#endif
+}
+#endif
+
+// MARK: - AssistedObjectiveCBridgeable
+
+extension List: AssistedObjectiveCBridgeable {
+    internal static func bridging(from objectiveCValue: Any, with metadata: Any?) -> List {
+        guard let objectiveCValue = objectiveCValue as? RLMArray<AnyObject> else { preconditionFailure() }
+        return List(rlmArray: objectiveCValue)
+    }
+
+    internal var bridged: (objectiveCValue: Any, metadata: Any?) {
+        return (objectiveCValue: _rlmArray, metadata: nil)
+    }
+}
+// MARK: - Unavailable
+
+extension List {
+    @available(*, unavailable, renamed: "remove(at:)")
+    public func remove(objectAtIndex: Int) { fatalError() }
+}