iosswiftuiviewstoryboarduistackview

Insert View Programmatically in storyboard designed Stackview in Swift iOS


I have created a stackview in storyboard which is having three buttons and I want to insert a separator in between all these three buttons, so I have created a separator blank view programmatically with frame CGRect(x: 0, y: 0, width: 1, height: 12) having gray colour. I am trying to insert this view in between all three buttons. But it's not working properly. I have option to add this separator on storyboard and hide-show that and it will work. But my buttons are dynamic in number so I want to insert separator programmatically in stackview.

How can we insert any view/any UI element programmatically in storyboard designed Stack view?

Storyboard:

enter image description here

Code:

@IBOutlet weak var mainStack: UIStackView!

 override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    let sep1 = getSeparatorView()
    let sep2 = getSeparatorView()
    let sep3 = getSeparatorView()
    mainStack.insertSubview(sep1, at: 1)
    mainStack.insertSubview(sep2, at: 3)
}

 func getSeparatorView() -> UIView {
        let separator = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 12))
        separator.backgroundColor = UIColor.lightGray
        return separator
    }

Note:

I tried by inserting insertArrangedSubview function but it looks like this (only one separator added with wrong width):

mainStack.insertArrangedSubview(sep1, at: 1)
        mainStack.insertArrangedSubview(sep2, at: 3)

enter image description here


Solution

  • There is a misunderstanding here. The stackView in Storyboard was designed with auto layout, on the other hand, separator is using frame. It cannot be compatible. So:

    1. As Paulw said, arrangedSubviews is the correct function.
    mainStack.insertArrangedSubview(sep1, at: 1)
    mainStack.insertArrangedSubview(sep2, at: 3)
    
    1. Convert the separator's frame to constraints.
    func getSeparatorView() -> UIView {
        ...
        separator.translatesAutoresizingMaskIntoConstraints = false
        separator.addConstraints([
            .init(item: separator, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 1),
            .init(item: separator, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 12)
        ])
        return separator
    }
    
    1. Change the stack properties for better layout, you can read the documentation here.
    mainStack.spacing = 8
    mainStack.distribution = .fill
    mainStack.alignment = .center
    

    Output:

    enter image description here