2

Hi all I'm new to SwiftUI and am trying to find a neat way to add or remove TextFields when either the plus or minus of a steeper is pressed.

I currently have

@State private var answers: [String] = ["", ""]
Stepper(onIncrement: {
    if(numberOfAnswers < 10){
        answers.append("")
        numberOfAnswers += 1
    }
    },
    onDecrement: {
        if(numberOfAnswers > 2){
        answers.removeLast()
        numberOfAnswers -= 1
        }
    }) {
ForEach(answers.indices, id: \.self) { index in
    TextField("Answer", text: $answers[index])
}

However this results in an Index out of bounds exception when onDecrement is called. I have tried wrapping the String to conform to Identifiable (with the @State inside the struct declaration), using ForEach(answers) however this produces a warning stating that the variable will not be updated.

I have tried solutions posted here but to no avail.

I do not need to persistently store the result of this, as it will be passed to a separate function making an API call on button press.

Any help for this would be much appreciated.

1 Answer 1

1

Here is fixed replicated code. Tested with Xcode 11.4 / iOS 13.4

struct DemoView: View {
    @State var numberOfAnswers = 2
    @State private var answers: [String] = ["", ""]

    var body: some View {
        Stepper(onIncrement: {
            if(self.numberOfAnswers < 10){
                self.answers.append("")
                self.numberOfAnswers += 1
            }
        },
                onDecrement: {
                    if(self.numberOfAnswers > 2){
                        self.answers.removeLast()
                        self.numberOfAnswers -= 1
                    }
        }) {
            ForEach(Array(answers.enumerated()), id: \.0) { i, _ in
                TextField("Answer", text: self.$answers[i])
            }
        }
    }
}

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks, exactly what I was looking for however on reflection could you please clarify the use of id: \.1, how does Swift use this as a keyPath for id? What does the 1 refer to? I understand that the enumerated() returns pairs of values and indices. Furthermore, I noticed you answered this, but I am still looking for a solution to the behaviour.
.enumerated return array of tuples [(index, element)], and tuple members can be accessed as .0 and .1, so \.1 is equivalent to previously used \.self
I'm having an issue with this solution only noticed through testing - sorry. When entering text into the dynamically added boxes, I can only type one character at a time, the first is often duplicated into the other boxes. Also, there are occasional index out of range exceptions. Thanks in advance for your help
Updated. Actually fix is id: \.0 in this simple demo. In real project I would recommend to have some model for each with own unique identifier.
Thanks for your response, however this solution crashes on removal of TextField, i.e. when stepper minus pressed. Do you mean a model wrapping a string with an identifier?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.