Attaching the demo code:
import SwiftUI
struct BufferTest: View {
@Binding var text: String
@State private var buffer: String = ""
@State private var presentModificationSheet: Bool = false
var bufferedBinding: Binding {
Binding {
text
} set: {
buffer = $0
if text != buffer {
presentModificationSheet = true
}
}
}
var body: some View {
Text("Binding: \(text)")
// Text("Buffer: \(buffer)")
InternalModder(binding: bufferedBinding)
.sheet(isPresented: $presentModificationSheet) {
TerminalSheet(text: $text, buffer: buffer)
}
}
struct InternalModder: View {
@Binding var binding: String
var body: some View {
Button("Set") { binding = "New Value" + (1...10).randomElement()!.formatted() }
}
}
struct TerminalSheet: View {
@Binding var text: String
var buffer: String
var body: some View {
Text("Binding: \(text)")
Text("Buffer: \(buffer)")
Button("Update") { text = buffer }
}
}
}
@available(iOS 17.0, *)
#Preview {
@Previewable @State var text = ""
BufferTest(text: $text)
}
Here, when pressing the button “Set” for first time, the sheet is presented but does not have the updated buffered value. However, mutations after that takes place correctly.
If we uncomment the
Text("Buffer: \(buffer)")
within BufferTest’s body, then the updates are taking place correctly.
Why does this happen ? and if it is the intended behavior, mutating like this isn’t recommended ?
Also the straightforward way to solve this is via onChange modifier:
.onChange(of: buffer) { new in
if new != text {
presentModificationSheet = true
}
}
