X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/53b27422d140022594fc241cca91c3183be57bca..48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff:/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 index 0000000..61f522a --- /dev/null +++ b/iOS/Pods/RealmSwift/RealmSwift/List.swift @@ -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`. + + Properties of `List` type defined on `Object` subclasses must be declared as `let` and cannot be `dynamic`. + */ +public final class List: 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) { + 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 { + return Results(_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 { + return Results(_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 { + 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(by sortDescriptors: S) -> Results + where S.Iterator.Element == SortDescriptor { + return Results(_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(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(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(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(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) -> 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 { + 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(_ subrange: Range, with newElements: C) + where C.Iterator.Element == Element { + for _ in subrange.lowerBound.. + + /// 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>) -> 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 + + /** + 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) -> SubSequence { + get { + return SubSequence(base: self, bounds: bounds) + } + set { + replaceSubrange(bounds.lowerBound..(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) { + removeSubrange(bounds.lowerBound..) { + removeSubrange(bounds.lowerBound...bounds.upperBound) + } + + //// :nodoc: + public func removeSubrange(_ bounds: CountableRange) { + for _ in bounds { + remove(at: bounds.lowerBound) + } + } + + /// :nodoc: + public func removeSubrange(_ bounds: CountableClosedRange) { + for _ in bounds { + remove(at: bounds.lowerBound) + } + } + + /// :nodoc: + public func removeSubrange(_ bounds: DefaultRandomAccessIndices) { + removeSubrange(bounds.startIndex..(_ subrange: ClosedRange, with newElements: C) + where C.Iterator.Element == Element { + removeSubrange(subrange) + insert(contentsOf: newElements, at: subrange.lowerBound) + } + + /// :nodoc: + public func replaceSubrange(_ subrange: CountableRange, with newElements: C) + where C.Iterator.Element == Element { + removeSubrange(subrange) + insert(contentsOf: newElements, at: subrange.lowerBound) + } + + /// :nodoc: + public func replaceSubrange(_ subrange: CountableClosedRange, with newElements: C) + where C.Iterator.Element == Element { + removeSubrange(subrange) + insert(contentsOf: newElements, at: subrange.lowerBound) + } + + /// :nodoc: + public func replaceSubrange(_ subrange: DefaultRandomAccessIndices, 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 + + /// :nodoc: + public subscript(slice: Range) -> 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 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() } +}