IdentityLink.swift 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. //
  2. // IdentityLink.swift
  3. // ark_ui_basic
  4. //
  5. // Audited for 6.5.4
  6. // Status: Complete
  7. // ID: 40EF7F17DC5632BC606B35EF926A7EA5 (SwiftUI)
  8. import Foundation
  9. @_spi(ForOpenSwiftUIOnly)
  10. import ark_ui_basic_core
  11. // MARK: - ViewIdentity
  12. package struct ViewIdentity: Hashable {
  13. package let seed: UInt32
  14. private static var nextSeed: UInt32 = 1
  15. package static let invalid = ViewIdentity(seed: .zero)
  16. package init() {
  17. let seed = ViewIdentity.nextSeed
  18. let next = seed &+ 1
  19. ViewIdentity.nextSeed = seed <= 1 ? 1 : next
  20. self.init(seed: seed)
  21. }
  22. private init(seed: UInt32) {
  23. self.seed = seed
  24. }
  25. package struct Tracker {
  26. package var id: ViewIdentity
  27. package var resetSeed: UInt32
  28. package mutating func update(
  29. for phase: ViewPhase
  30. ) -> (value: ViewIdentity, changed: Bool) {
  31. guard phase.resetSeed != resetSeed || id == .invalid else {
  32. return (id, false)
  33. }
  34. id = .init()
  35. resetSeed = phase.resetSeed
  36. return (id, true)
  37. }
  38. }
  39. }
  40. // MARK: - IdentityLink
  41. package struct IdentityLink: DynamicProperty {
  42. var _value: ViewIdentity
  43. package static func _makeProperty<Value>(
  44. in buffer: inout _DynamicPropertyBuffer,
  45. container: _GraphValue<Value>,
  46. fieldOffset: Int,
  47. inputs: inout _GraphInputs
  48. ) {
  49. let box = IdentityLinkBox(id: .invalid)
  50. buffer.append(box, fieldOffset: fieldOffset)
  51. }
  52. }
  53. // MARK: - IdentityLinkBox
  54. private struct IdentityLinkBox: DynamicPropertyBox {
  55. var id: ViewIdentity
  56. mutating func reset() {
  57. id = .invalid
  58. }
  59. mutating func update(
  60. property: inout IdentityLink,
  61. phase: ViewPhase
  62. ) -> Bool {
  63. let newID = id == .invalid ? ViewIdentity() : id
  64. property._value = newID
  65. defer { id = newID }
  66. return newID != id
  67. }
  68. }