UIStackView
iOS Development
Swift Programming
Layout Management
Programmatically Adding Views

Add views in UIStackView programmatically

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

UIStackView is one of the simplest ways to build dynamic layouts in UIKit without writing complex manual constraints for every subview. Adding arranged subviews programmatically is especially useful for forms, settings screens, and dynamic content blocks. This guide shows setup, insertion, removal, and performance-friendly update patterns.

Create and Configure a Stack View

Start by creating a stack view, turning off autoresizing translation, and pinning it with constraints.

swift
1import UIKit
2
3final class ProfileViewController: UIViewController {
4    private let stackView = UIStackView()
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        view.backgroundColor = .systemBackground
9
10        stackView.axis = .vertical
11        stackView.spacing = 12
12        stackView.alignment = .fill
13        stackView.distribution = .fill
14        stackView.translatesAutoresizingMaskIntoConstraints = false
15
16        view.addSubview(stackView)
17
18        NSLayoutConstraint.activate([
19            stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
20            stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
21            stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20)
22        ])
23    }
24}

This gives a stable container where arranged subviews can be added in sequence.

Add Arranged Subviews Programmatically

Use addArrangedSubview for views that should participate in stack layout.

swift
1private func buildInitialContent() {
2    let titleLabel = UILabel()
3    titleLabel.text = "Profile"
4    titleLabel.font = .preferredFont(forTextStyle: .title2)
5
6    let nameField = UITextField()
7    nameField.placeholder = "Name"
8    nameField.borderStyle = .roundedRect
9
10    let emailField = UITextField()
11    emailField.placeholder = "Email"
12    emailField.borderStyle = .roundedRect
13
14    stackView.addArrangedSubview(titleLabel)
15    stackView.addArrangedSubview(nameField)
16    stackView.addArrangedSubview(emailField)
17}

Call buildInitialContent() from viewDidLoad after stack configuration.

Insert, Remove, and Reorder Views

Dynamic UIs often need insertion at specific positions.

swift
1func insertWarning(_ message: String) {
2    let warning = UILabel()
3    warning.text = message
4    warning.textColor = .systemRed
5    warning.numberOfLines = 0
6
7    let insertionIndex = min(1, stackView.arrangedSubviews.count)
8    stackView.insertArrangedSubview(warning, at: insertionIndex)
9}

For removal, call both removeArrangedSubview and removeFromSuperview.

swift
1func removeAllRows() {
2    for view in stackView.arrangedSubviews {
3        stackView.removeArrangedSubview(view)
4        view.removeFromSuperview()
5    }
6}

If you only remove from arranged subviews, the view can remain in hierarchy and still consume memory.

Use Spacer and Container Views Correctly

When per-row layout is complex, wrap controls in a container view and add constraints inside that container.

swift
1func makeRow(title: String, control: UIView) -> UIView {
2    let row = UIStackView()
3    row.axis = .horizontal
4    row.alignment = .center
5    row.spacing = 8
6
7    let label = UILabel()
8    label.text = title
9    label.setContentHuggingPriority(.required, for: .horizontal)
10
11    row.addArrangedSubview(label)
12    row.addArrangedSubview(control)
13    return row
14}

This keeps the parent stack simple while enabling flexible row-level behavior.

Animate Stack Updates

UIStackView updates can be animated using UIView.animate with layoutIfNeeded.

swift
1func toggleAdvancedSection(_ visible: Bool, sectionView: UIView) {
2    sectionView.isHidden = !visible
3
4    UIView.animate(withDuration: 0.25) {
5        self.view.layoutIfNeeded()
6    }
7}

Hiding arranged subviews is often better than removing and recreating when the section will be shown again soon.

Build the Stack from View Models

A clean pattern is generating arranged subviews from data models. This keeps UI updates deterministic and easier to test.

swift
1struct FieldModel {
2    let title: String
3    let placeholder: String
4}
5
6func apply(models: [FieldModel]) {
7    removeAllRows()
8
9    for model in models {
10        let field = UITextField()
11        field.placeholder = model.placeholder
12        field.borderStyle = .roundedRect
13
14        let row = makeRow(title: model.title, control: field)
15        stackView.addArrangedSubview(row)
16    }
17}

This approach avoids scattered ad-hoc insertions and makes dynamic forms simpler to maintain when requirements change.

For very large dynamic lists, consider pairing stack views with a scroll view and creating rows lazily to reduce startup work. UIStackView is excellent for moderate dynamic content, but table or collection views scale better for large datasets. Choosing the correct container early prevents expensive UI rewrites later.

Profile layout passes in Instruments when you update many arranged subviews at once, then batch updates if frame calculation becomes a bottleneck.

Common Pitfalls

  • Adding subviews with addSubview instead of addArrangedSubview when stack layout is expected.
  • Removing arranged views without calling removeFromSuperview.
  • Overusing nested stack views without clear structure, making layout debugging hard.
  • Forgetting content hugging and compression priorities for rows with labels and fields.
  • Rebuilding entire stack on each update instead of updating only affected views.

Summary

  • Configure and constrain UIStackView first, then add arranged subviews.
  • Use addArrangedSubview for layout-managed elements.
  • Remove views with both removeArrangedSubview and removeFromSuperview.
  • Wrap complex row layouts in nested stacks or container views.
  • Animate visibility and layout changes for smoother dynamic interfaces.

Course illustration
Course illustration

All Rights Reserved.