LinkingObjects.swift 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 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. import Foundation
  19. import Realm
  20. /**
  21. `LinkingObjects` is an auto-updating container type. It represents zero or more objects that are linked to its owning
  22. model object through a property relationship.
  23. `LinkingObjects` can be queried with the same predicates as `List<Element>` and `Results<Element>`.
  24. `LinkingObjects` always reflects the current state of the Realm on the current thread, including during write
  25. transactions on the current thread. The one exception to this is when using `for...in` enumeration, which will always
  26. enumerate over the linking objects that were present when the enumeration is begun, even if some of them are deleted or
  27. modified to no longer link to the target object during the enumeration.
  28. `LinkingObjects` can only be used as a property on `Object` models. Properties of this type must be declared as `let`
  29. and cannot be `dynamic`.
  30. */
  31. @frozen public struct LinkingObjects<Element: ObjectBase & RealmCollectionValue>: RealmCollectionImpl {
  32. // MARK: Initializers
  33. /**
  34. Creates an instance of a `LinkingObjects`. This initializer should only be called when declaring a property on a
  35. Realm model.
  36. - parameter type: The type of the object owning the property the linking objects should refer to.
  37. - parameter propertyName: The property name of the property the linking objects should refer to.
  38. */
  39. public init(fromType _: Element.Type, property propertyName: String) {
  40. self.propertyName = propertyName
  41. }
  42. /// A human-readable description of the objects represented by the linking objects.
  43. public var description: String {
  44. if realm == nil {
  45. var this = self
  46. return withUnsafePointer(to: &this) {
  47. return "LinkingObjects<\(Element.className())> <\($0)> (\n\n)"
  48. }
  49. }
  50. return RLMDescriptionWithMaxDepth("LinkingObjects", collection, RLMDescriptionMaxDepth)
  51. }
  52. // MARK: Object Retrieval
  53. /**
  54. Returns the object at the given `index`.
  55. - parameter index: The index.
  56. */
  57. public subscript(index: Int) -> Element {
  58. if let lastAccessedNames = lastAccessedNames {
  59. return Element.keyPathRecorder(with: lastAccessedNames)
  60. }
  61. throwForNegativeIndex(index)
  62. return collection[UInt(index)] as! Element
  63. }
  64. // MARK: Equatable
  65. public static func == (lhs: LinkingObjects<Element>, rhs: LinkingObjects<Element>) -> Bool {
  66. lhs.collection.isEqual(rhs.collection)
  67. }
  68. // MARK: Implementation
  69. internal init(propertyName: String, handle: RLMLinkingObjectsHandle?) {
  70. self.propertyName = propertyName
  71. self.handle = handle
  72. }
  73. internal init(collection: RLMCollection) {
  74. self.propertyName = ""
  75. self.handle = RLMLinkingObjectsHandle(linkingObjects: collection as! RLMResults<AnyObject>)
  76. }
  77. internal var collection: RLMCollection {
  78. return handle?.results ?? RLMResults<AnyObject>.emptyDetached()
  79. }
  80. internal var propertyName: String
  81. internal var handle: RLMLinkingObjectsHandle?
  82. internal var lastAccessedNames: NSMutableArray?
  83. /// :nodoc:
  84. public func makeIterator() -> RLMIterator<Element> {
  85. return RLMIterator(collection: collection)
  86. }
  87. }