Working with Xcode 15 on the latest available version of macOS 14, I have a very simple SwiftUI form whose Save button is supposed to be disabled only as long as both of the form fields are filled in:
import SwiftUI
import SwiftData
struct AddToDoScreen: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.modelContext) private var context
@State private var name: String = ""
@State private var priority: Int?
private var isFormValid: Bool {
!name.isEmpty && priority != nil
}
var body: some View {
Form {
TextField("Name", text: $name)
TextField("Priority", value: $priority, format: .number)
}
.navigationTitle("Add ToDo")
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Dismiss") {
dismiss()
}
}
ToolbarItem(placement: .topBarTrailing) {
Button("Save") {
guard let priority = priority else { return }
let toDo = ToDo(name: name, priority: priority)
context.insert(toDo)
do {
try context.save()
} catch {
print(error.localizedDescription)
}
dismiss()
}.disabled(!isFormValid)
}
}
}
}
GitHub link of the project: https://github.com/atilsamancioglu/iOS50-SwiftDataToDo
Is there anything wrong with my code or is this another Apple bug? Is there anything I can do as a fix or workaround?
You need to type in a number in the second text field since you used format: .number
. If it can't parse the text as a number then it sets your Int?
state to nil and thats why the button does not enable.
FYI I looked at your project and it's best if you switch from sheet(isPresented:)
to sheet(item:)
. In the button action create the new model object, store it as an @State var item
that you use as the sheet's binding. Then in the AddToDoScreen
bind your text fields to that object instead of those independent states.