iosswiftuiviewuistackviewremovefromsuperview

Removing views from vertical stackview


noob question as always.

I have ViewController that contains a vertical stackview. Inside the stack are labels and textfields (the label describes the text to be inputted into the textfield). Depending on what the user selects from a list of items in a table on a previous screen, I want to change which labels+textfields get displayed to the user.

I'd like to remove both in one go for simplicity. I've been able to remove a textfield+label from view using tags. But I can't have the same tag number assigned to both a label and textfield then remove them both from view at once. Currently removing a label and textfield at once looks like...

    if let viewWithTag = self.view.viewWithTag(1) {
        viewWithTag.removeFromSuperview()
    }
    if let viewWithTag = self.view.viewWithTag(2) {
        viewWithTag.removeFromSuperview()
    }

With quite a few label+textfields to work through this could get messy.

Next I looked at inserting a UIView into the stack and then adding my label+textfield into that view. Then I can assign a tag to the UIView and remove all at once, but the uiviews alignment inside the vertical stackview is a mess and I don't really know how to fix it. Doesn't seem like the right way to go?

Wonder if I need to stick the tag numbers into an array of some sort and create a function to simplify the remove with tag process?

Any help on how to approach appreciated.


Solution

  • The views in a UIStackView are already an indexed array, accessible via the stack view's .arrangedSubviews property.

    So, suppose you have 8 label/field pairs, they will be indexed like this:

    enter image description here

    If you want to remove the 4th pair (Label 4 and Field 4), you can do this:

    stackView.arrangedSubviews[6].removeFromSuperview()
    

    That removes "Label 4" (remember, array indexes are zero-based).

    Now, "Field 4" is at [6], so just call it again:

    stackView.arrangedSubviews[6].removeFromSuperview()
    

    That said, depending on what you're doing, you may find it easier to ADD your label/field pairs at runtime.

    Something along these lines:

        let labels: [String] = [
            "First name",
            "Last name",
            "Age",
            "Favorite color",
            "Favorite food",
            "Favorite animal",
        ]
        
        // based on selection from previous view controller,
        //  let's show First name, Last name, Fav color and animal
        let pairsToShow: [Int] = [0, 1, 3, 5]
        
        pairsToShow.forEach { idx in
            let v = UILabel()
            v.text = labels[idx]
            v.backgroundColor = .yellow
            stackView.addArrangedSubview(v)
            let t = UITextField()
            t.borderStyle = .roundedRect
            stackView.addArrangedSubview(t)
        }
    

    and we end up with this:

    enter image description here