Here's the text field code:
import SwiftUI
import SwiftUIIntrospect
class TextFieldKeyboardBehavior: UIView, UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
return false
}
}
struct AddIngredientsView: View {
@State var ingredient = ""
@State var ingredientsArray: [String] = []
var textFieldKeyboardBehavior = TextFieldKeyboardBehavior()
var body: some View {
VStack {
if ingredientsArray.count > 0 {
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 10) {
ForEach(ingredientsArray, id: \.self) { ingredient in
Text("\(ingredient)")
}
}
}
}
// do something here to append input data in ingredientsArray???
TextField("Enter an ingredient", text: $ingredient)
.multilineTextAlignment(.leading)
.foregroundStyle(Color("SemiDarkGray"))
.introspect(.textField, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { textField in
textField.delegate = textFieldKeyboardBehavior
}
}
}
}
}
what i'd like to achieve is that every time a user inputs data in the textfield and then clicks submit in the keyboard, the input data will get appended into an array and be shown on the screen using ForEach
or List
.
i've tried using onSubmit
but Introspect overrides with it which causes onSubmit
to not work at all. The reason I'm using Introspect is because I want the keyboard to be visible even after the user clicks submit on the keyboard.
i've also tried using FocusedState
instead of Introspect in order to prevent the keyboard from dismissing but that unfortunately causes a weird bounce animation which does not look pleasing to the eye.
here's an example of how i want it to function:
Since you already control textFieldShouldReturn
, just do whatever you want to do in there.
class TextFieldKeyboardBehavior: NSObject, UITextFieldDelegate, ObservableObject {
var onSubmit: (() -> Void)?
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
onSubmit?()
return false
}
}
Note that I made this an ObservableObject
. This way, you can use a @StateObject
to persist it, without having to create a new object every time the View
struct is initialised.
Then in introspect
, you can just do:
textFieldKeyboardBehavior.onSubmit = { ... }
textField.delegate = textFieldKeyboardBehavior
Here is a complete example:
struct ContentView: View {
@State private var ingredient = ""
@State private var ingredients = [String]()
@StateObject var textFieldKeyboardBehavior = TextFieldKeyboardBehavior()
var body: some View {
VStack {
ForEach(ingredients, id: \.self) {
Text($0)
}
TextField("Enter an ingredient", text: $ingredient)
.introspect(.textField, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { textField in
textFieldKeyboardBehavior.onSubmit = {
withAnimation {
ingredients.append(ingredient)
}
}
textField.delegate = textFieldKeyboardBehavior
}
}
}
}