Search code examples
swiftiphoneswiftuiios15

SwiftUI iOS15 Binding ForEach is dismissing TextField KeyBoard


as suggested in WWDC21 "What's new in SwiftUI", now it's possible to manage binding inside ForEach, but I've a problem with TextField, if I add a character, the KeyBoard is dismissing.

struct TESTVIEW: View {

    public struct MyTask: Identifiable, Codable, Hashable {
        public var id: UUID = UUID()
        var title: String = ""
    }

    @State var tasks: [MyTask] = []
    
    
    var body: some View {
          
        VStack {
            Text("NEW")
            List {
                ForEach ($tasks, id:\.self) { $task in
                    TextField("Click", text: $task.title)
                }
                .onDelete(perform: delete)
                Button(action: {
                    tasks.append(MyTask())
                }) {
                    Label("New task", systemImage: "plus.circle.fill")
                }
                .padding()
                .accentColor(.white)
            }
            Text("OLD")
            List {
                ForEach (tasks.indices, id:\.self) { idx in
                    let bindingTask = Binding(get: {tasks[idx]},set: {value in tasks[idx] = value})
                    TextField("Click", text: bindingTask.title)
                }
                .onDelete(perform: delete)
                Button(action: {
                    tasks.append(MyTask())
                }) {
                    Label("New task", systemImage: "plus.circle.fill")
                }
                .padding()
                .accentColor(.white)
            }
        }
        .preferredColorScheme(.dark)
    }

    func delete(at offsets: IndexSet) {
        tasks.remove(atOffsets: offsets)
    }

}


struct TESTVIEW_Previews: PreviewProvider {
    static var previews: some View {
        TESTVIEW()
    }
}

Any suggestion?


Solution

  • Your struct conforms to Identifiable, so it’s simply:

    ForEach ($tasks) { $task in
          TextField("Click", text: $task.title)
    }