Swift
iOS Development
UIButton
Mobile App Development
Xcode

Changing UIButton text

Master System Design with Codemia

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

Introduction

Changing a button title in UIKit is simple, but there is a correct API for it and a few easy mistakes to avoid. In most cases, you should update a UIButton by setting the title for a control state, not by mutating the internal label directly.

Use setTitle for State-Aware Text

The standard way to change a button's visible text is setTitle(_:for:):

swift
1import UIKit
2
3final class ViewController: UIViewController {
4    @IBOutlet private weak var actionButton: UIButton!
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        actionButton.setTitle("Start", for: .normal)
9    }
10}

This matters because a UIButton can have different titles for different states such as .normal, .highlighted, .disabled, and .selected.

For example:

swift
actionButton.setTitle("Submit", for: .normal)
actionButton.setTitle("Submitting...", for: .disabled)

When the button becomes disabled, UIKit can show the alternate title automatically.

Update the Title in Response to User Actions

The most common pattern is changing the title inside an action method:

swift
1import UIKit
2
3final class ViewController: UIViewController {
4    @IBOutlet private weak var toggleButton: UIButton!
5
6    @IBAction private func togglePressed(_ sender: UIButton) {
7        let isSelected = !sender.isSelected
8        sender.isSelected = isSelected
9        sender.setTitle(isSelected ? "Selected" : "Select", for: .normal)
10    }
11}

This is the right level of abstraction because you are updating the button, not its implementation details.

Do Not Change titleLabel?.text Directly

A common mistake is:

swift
button.titleLabel?.text = "Wrong approach"

That can appear to work briefly in debugging, but it bypasses the button's state management and often does not update the UI the way you expect. UIButton owns its label configuration, so use the public button API instead.

The correct version is:

swift
button.setTitle("Correct approach", for: .normal)

Make Sure UI Updates Happen on the Main Thread

If the text changes after a network request or background task, switch back to the main thread before touching the button:

swift
1import UIKit
2
3func loadData(button: UIButton) {
4    Task.detached {
5        try? await Task.sleep(nanoseconds: 500_000_000)
6
7        await MainActor.run {
8            button.setTitle("Done", for: .normal)
9            button.isEnabled = true
10        }
11    }
12}

UIKit is not thread-safe, so background updates can cause subtle bugs or warnings.

Storyboard, Outlet, and Configuration Notes

If the button is connected from Interface Builder, make sure the outlet exists before changing the title. viewDidLoad is usually a safe place for initial setup.

Also remember that the title you set in a storyboard is only the initial value. Once the view controller loads, your code can replace it at any time.

If the app uses newer UIButton.Configuration APIs, the button may also have configuration-driven appearance rules. Even then, setTitle remains the clearest default choice for standard UIKit code unless the button is fully configuration-based across the screen.

If the title carries important meaning, also check localization and layout so longer translated strings still fit the button cleanly.

Common Pitfalls

  • Changing titleLabel?.text instead of calling setTitle(_:for:).
  • Setting a title for .normal and then wondering why a disabled or selected button still shows different text.
  • Updating the button from a background thread after async work.
  • Forgetting that an outlet is nil until the view has loaded.
  • Mixing storyboard defaults with code changes and then assuming Interface Builder is overriding runtime behavior.

Summary

  • Use setTitle(_:for:) to change a UIButton title.
  • Set titles per control state when the button needs different labels in different situations.
  • Avoid mutating titleLabel directly because it bypasses button state handling.
  • Update UIKit controls on the main thread.
  • For most apps, a title change in viewDidLoad or an action method is the simplest correct approach.

Course illustration
Course illustration

All Rights Reserved.