Guys.
My WatchOS app allows to create Goals. I am trying to disable the button if the title was used previously in other goal or the user entered nothing in the textfield.
So I tried to fetch my data, and wrote .disabled(goalTitle == item.goalTitle)
. However it leads to the problem, that if there are no created goals, the button disappears. In other case, after entering the title that exists, it duplicates the buttons - one disabled and one is working.
Here is the code of my view:
struct AddGoalView: View {
@State private var goalTitle = ""
@FetchRequest (
entity:NewGoal.entity(),
sortDescriptors:[NSSortDescriptor(keyPath: \NewGoal.dateAdded, ascending: false)],
animation: .easeInOut )
var results:FetchedResults<NewGoal>
@Environment(\.managedObjectContext) var context
@Environment(\.presentationMode) var presentationMode
var body: some View {
ScrollView{
VStack (alignment: .leading, spacing: 6){
TextField("Goal Name...", text: $goalTitle)
.padding(.bottom)
ForEach(results){item in ///---> This leads to the Button duplicating
Button(action: addGoal) {
Text("Add Goal")
}
.frame(maxWidth: .infinity, alignment: .center)
.disabled(goalTitle == "")
.disabled(goalTitle == item.goalTitle) ///---> Here I am trying to disable a button when the user writes down the existed title, to prevent Goal duplicates.
}
}
}
}
private func addGoal(){
let goal = NewGoal(context: context)
goal.goalTitle = goalTitle
goal.dateAdded = Date()
do{
try context.save()
presentationMode.wrappedValue.dismiss()
}catch let err{
print(err.localizedDescription)
}
}
}
Instead of using a ForEach
to loop through your elements, you can use .contains(where:)
on results
to determine if there's already a goal that uses that title:
var body: some View {
ScrollView{
VStack (alignment: .leading, spacing: 6){
TextField("Goal Name...", text: $goalTitle)
.padding(.bottom)
Button(action: addGoal) {
Text("Add Goal")
}.disabled(
goalTitle.isEmpty ||
results.contains(where: { $0.goalTitle == goalTitle})
)
}
}
}