Removing views from vertical stackview

74 Views Asked by At

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.

2

There are 2 best solutions below

1
DonMag On BEST ANSWER

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

0
excitedmicrobe On

Probably use a UIView extension?

extension UIView {
  func remove(_ tag:Int) {
     if let parent = self.viewWithTag(tag) {
        parent.removeFromSuperview()
     }
   }
}

Then use:

self.view.remove(1)