Created
December 2, 2023 15:01
-
-
Save mbrandonw/db904f2ad544da594eecd8c56ce86212 to your computer and use it in GitHub Desktop.
FB12969716
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# FB12969716 | |
// FB: `Form` and | |
// | |
// Paste this into a fresh SwiftUI project's ContentView.swift to see a bug with `Form` views with | |
// conditional child views that use `@State`. | |
// | |
// 1. Tap "Toggle" to show the child view with a new model | |
// 2. Tap "+" in the child view to increment the model's state from 0 to another number | |
// 3. Tap "Toggle" two times to hide the child and then show it again | |
// | |
// Note that the child view does not show "0", as expected with the newly assigned model, but | |
// instead shows the previous incremented count. The child view's `@State` is still holding onto the | |
// old stale model, _not_ the model that lives in the parent `ContentView`. | |
// | |
// Workarounds: | |
// | |
// * Don't use `Form`. If you swap `Form` out for a `VStack`, the child view uses the freshest | |
// model for state. | |
// * Drop the use of `@State`. | |
import SwiftUI | |
@Observable | |
class Model { | |
var count = 0 | |
} | |
struct ContentView: View { | |
@State var model: Model? | |
var body: some View { | |
Form { // 👈 Change this to 'VStack' to fix the problem | |
Button("Toggle") { | |
model = model == nil ? Model() : nil | |
} | |
if let model = model { | |
ChildView(model: model) | |
} | |
} | |
} | |
} | |
struct ChildView: View { | |
@State var model: Model // 👈 Or remove '@State' | |
var body: some View { | |
HStack { | |
Text("\(model.count)") | |
Button("+") { | |
model.count += 1 | |
} | |
} | |
} | |
} | |
#Preview { | |
ContentView() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment