WeakObjectSet.swift 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import Foundation
  2. struct WeakObject<T: AnyObject>: Equatable, Hashable {
  3. private let identifier: ObjectIdentifier
  4. weak var object: T?
  5. init(_ object: T) {
  6. self.object = object
  7. identifier = ObjectIdentifier(object)
  8. }
  9. func hash(into hasher: inout Hasher) {
  10. hasher.combine(identifier)
  11. }
  12. static func == (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
  13. lhs.identifier == rhs.identifier
  14. }
  15. }
  16. struct WeakObjectSet<T: AnyObject>: Sequence {
  17. var objects: Set<WeakObject<T>>
  18. init() {
  19. objects = Set<WeakObject<T>>([])
  20. }
  21. init(_ object: T) {
  22. objects = Set<WeakObject<T>>([WeakObject(object)])
  23. }
  24. init(_ objects: [T]) {
  25. self.objects = Set<WeakObject<T>>(objects.map { WeakObject($0) })
  26. }
  27. var allObjects: [T] {
  28. objects.compactMap(\.object)
  29. }
  30. func contains(_ object: T) -> Bool {
  31. objects.contains(WeakObject(object))
  32. }
  33. mutating func add(_ object: T) {
  34. // prevent ObjectIdentifier be reused
  35. if contains(object) {
  36. remove(object)
  37. }
  38. objects.insert(WeakObject(object))
  39. }
  40. mutating func add(_ objects: [T]) {
  41. objects.forEach { self.add($0) }
  42. }
  43. mutating func remove(_ object: T) {
  44. objects.remove(WeakObject<T>(object))
  45. }
  46. mutating func remove(_ objects: [T]) {
  47. objects.forEach { self.remove($0) }
  48. }
  49. func makeIterator() -> AnyIterator<T> {
  50. let objects = allObjects
  51. var index = 0
  52. return AnyIterator {
  53. defer { index += 1 }
  54. return index < objects.count ? objects[index] : nil
  55. }
  56. }
  57. }