1
0

EnvironmentModifier.swift 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. struct EnvironmentModifier<Child: View>: View {
  2. var body: TupleView1<Child>
  3. var modification: (EnvironmentValues) -> EnvironmentValues
  4. init(_ child: Child, modification: @escaping (EnvironmentValues) -> EnvironmentValues) {
  5. self.body = TupleView1(child)
  6. self.modification = modification
  7. }
  8. func children<Backend: BaseAppBackend>(
  9. backend: Backend,
  10. snapshots: [ViewGraphSnapshotter.NodeSnapshot]?,
  11. environment: EnvironmentValues
  12. ) -> any ViewGraphNodeChildren {
  13. body.children(
  14. backend: backend,
  15. snapshots: snapshots,
  16. environment: modification(environment)
  17. )
  18. }
  19. func computeLayout<Backend: BaseAppBackend>(
  20. _ widget: Backend.Widget,
  21. children: any ViewGraphNodeChildren,
  22. proposedSize: ProposedViewSize,
  23. environment: EnvironmentValues,
  24. backend: Backend
  25. ) -> ViewLayoutResult {
  26. body.computeLayout(
  27. widget,
  28. children: children,
  29. proposedSize: proposedSize,
  30. environment: modification(environment),
  31. backend: backend
  32. )
  33. }
  34. func commit<Backend: BaseAppBackend>(
  35. _ widget: Backend.Widget,
  36. children: any ViewGraphNodeChildren,
  37. layout: ViewLayoutResult,
  38. environment: EnvironmentValues,
  39. backend: Backend
  40. ) {
  41. body.commit(
  42. widget,
  43. children: children,
  44. layout: layout,
  45. environment: modification(environment),
  46. backend: backend
  47. )
  48. }
  49. public var _asMenuItems: [MenuItem] {
  50. self.body._asMenuItems.map { menuItem in
  51. .modifiedEnvironment({ menuItem }, { self.modification })
  52. }
  53. }
  54. }
  55. extension View {
  56. /// Modifies the environment of the View its applied to
  57. public func environment<T>(_ keyPath: WritableKeyPath<EnvironmentValues, T>, _ newValue: T)
  58. -> some View
  59. {
  60. EnvironmentModifier(self) { environment in
  61. environment.with(keyPath, newValue)
  62. }
  63. }
  64. /// Adds an observable object to the environment of the enclosed View.
  65. /// You are responsible for ensuring that the object is being observed
  66. /// by a parent view, as this modifier does not perform any observation.
  67. public func environment<T: ObservableObject>(_ object: T) -> some View {
  68. EnvironmentModifier(self) { environment in
  69. var environment = environment
  70. environment[observable: T.self] = object
  71. return environment
  72. }
  73. }
  74. }