Using IfLet requires cancellation/confirmation twice
appfrosch opened this issue · 4 comments
Describe the bug
I am driving a detail screen with an Edit/Confirm logic. Entering the "edit" works as expected, but the Confirm- and the Cancel-button need to be tapped twice in order to end editing. The editing itself is bound to an optional string that is set when the Edit-button is tapped.
The view is driven off of an IfLet
.
Please forgive me if this is something explained in one of your videos–as a subscriber of your content feel free to just point me to a related video if available :-)
To Reproduce
This is a sample project mimicking the behaviour I see in my project.
import SwiftUI
import SwiftUINavigation
@main
struct so_IfLetIssueApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var title = "Some fancy title"
@State private var editingTitle: String?
var body: some View {
NavigationStack {
Form {
IfLet($editingTitle) { $editingTitle in
TextField("Title", text: $editingTitle)
} else: {
Text(title)
}
}
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button(editingTitle == nil ? "Edit" : "Confirm") {
if let editingTitle {
title = editingTitle
self.editingTitle = nil
} else {
editingTitle = title
}
}
}
if editingTitle != nil {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
editingTitle = nil
}
}
}
ToolbarItem(placement: .bottomBar) {
Text("editingTitle is \"\(editingTitle == nil ? "nil" : editingTitle!)\"")
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Expected behavior
Tapping the "Confirm" or the "Cancel" button once should end editing by setting the optional binding to nil.
Screencast
Simulator.Screen.Recording.-.iPhone.SE.3rd.generation.-.2022-11-17.at.08.42.01.mp4
Environment
- swiftui-navigation version [e.g. 0.1.0]
- Xcode Version 14.1 (14B47b)
- Swift 5.5
- OS: macOS 12.6.1 (21G217)
Hi @appfrosch, thanks for the nice repro of this problem!
Unfortunately, this is a long-standing, known SwiftUI bug :/
The problem is, for whatever reason, TextField
s always write twice to their bindings. We filed a bug for it (gist), so if you have the time we recommend you duplicate.
Luckily there is a word around. You just need to transform the binding you hand to TextField
so that it removes duplicate writes. And this library even comes with that tool:
TextField("Title", text: $editingTitle.removeDuplicates())
Can you confirm that works for you?
Hi @appfrosch, glad it worked!
We also have an update to swiftui-navigation coming out next week that will fix this problem in a way that does not require you to litter removeDuplicates
on all your text field bindings. So be sure to update when we release. 😁
This is fixed by default in 0.4.x 😄