Post

Replies

Boosts

Views

Activity

Binding a constant at init triggers View refresh
Greetings, Context Let's imagine 2 possible root Views: House and Castle. They can both present a Room view and this room view can show a Bed view. Let's also assume, for the sake of the example, that I want to pass the "$sheet" (Identifiable enum) from either House or Castle - which are 2 different enums - all the way to Bed, so that Bed can dismiss back to rootView. So I use a Binding. Visually, the UI flow is House --> \ Room --> Bed Castle --> / In RoomView and BedView, I expected to receive either a HouseSheet or a CastleSheet. So by receiving one at init, I set to a constant nil the other. For example, if I open a RoomView (or BedView) from a HouseView, the code would be init(parentHouseSheet: Binding<HouseSheet?>) { self._parentHouseSheet = parentHouseSheet self._parentCastleSheet = .constant(nil) self.from = .house } init(parentCastleSheet: Binding<CastleSheet?>) { self._parentHouseSheet = .constant(nil) self._parentCastleSheet = parentCastleSheet self.from = .castle } Problem My problem now is that the .constant(nil) appears to change and triggers a refresh! By using a simple Self._printChanges() I get the following when I navigate to a BedView (from a House origin!). RoomView: _parentCastleSheet changed. // Why? It's a binded constant and I'm not even touching RoomView at all. BedView: @self, @identity, _parentCastleSheet changed. BedView: @self, _parentCastleSheet changed. // Same why? Full code // House & Castle enum BuildingOrigin: String { case house case castle } enum HouseSheet: String, Hashable, Identifiable { case room var id: String { return self.rawValue } } enum CastleSheet: String, Hashable, Identifiable { case room var id: String { return self.rawValue } } // I only show HouseView for this example. struct HouseView: View { @State private var sheet: HouseSheet? var body: some View { let _ = Self._printChanges() VStack { Button("Open Room (Sheet)") { self.sheet = .room } } .padding() .sheet(item: $sheet) { sheet in switch sheet { case .room: RoomView(houseSheet: $sheet) } } } } // Room enum RoomViewDestination: String, Hashable { case bed } struct RoomView: View { @State private var path = NavigationPath() @Binding var parentHouseSheet: HouseSheet? @Binding var parentCastleSheet: CastleSheet? let from: BuildingOrigin init(houseSheet: Binding<HouseSheet?>) { self._parentHouseSheet = houseSheet self._parentCastleSheet = .constant(nil) self.from = .house } init(castleSheet: Binding<CastleSheet?>) { self._parentHouseSheet = .constant(nil) self._parentCastleSheet = castleSheet self.from = .castle } var body: some View { let _ = Self._printChanges() NavigationStack(path: $path) { List { NavigationLink(value: RoomViewDestination.bed) { Text("Open Bed (Navigation)") } } .navigationDestination(for: RoomViewDestination.self) { destination in switch destination { case .bed: switch self.from { case .house: BedView(parentHouseSheet: $parentHouseSheet) case .castle: BedView(parentCastleSheet: $parentCastleSheet) } } } } } } // Bed struct BedView: View { @Binding var parentHouseSheet: HouseSheet? @Binding var parentCastleSheet: CastleSheet? let from: BuildingOrigin init(parentHouseSheet: Binding<HouseSheet?>) { self._parentHouseSheet = parentHouseSheet self._parentCastleSheet = .constant(nil) self.from = .house } init(parentCastleSheet: Binding<CastleSheet?>) { self._parentHouseSheet = .constant(nil) self._parentCastleSheet = parentCastleSheet self.from = .castle } var body: some View { let _ = Self._printChanges() Text("The \(from.rawValue) has a nice bed.") } }
0
1
261
Jul ’24