Xcode
iOS development
programmatically add action
UIButton
Swift programming

How do you add an action to a button programmatically in xcode

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

To add a button action programmatically in UIKit, create the UIButton, add it to the view hierarchy, and register a target-action pair with addTarget. The most common event is .touchUpInside, which fires when the user taps and releases the button inside its bounds.

The Target-Action Pattern

UIKit buttons use the target-action mechanism. Instead of assigning an inline callback, you tell the button:

  • which object should receive the event
  • which method should be called
  • which control event should trigger it

In Swift, that usually looks like button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside).

The selector method must be visible to the Objective-C runtime, so it needs @objc.

A Complete Example

swift
1import UIKit
2
3final class ViewController: UIViewController {
4    private let actionButton: UIButton = {
5        let button = UIButton(type: .system)
6        button.setTitle("Tap Me", for: .normal)
7        button.translatesAutoresizingMaskIntoConstraints = false
8        return button
9    }()
10
11    override func viewDidLoad() {
12        super.viewDidLoad()
13        view.backgroundColor = .systemBackground
14
15        view.addSubview(actionButton)
16
17        NSLayoutConstraint.activate([
18            actionButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
19            actionButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
20        ])
21
22        actionButton.addTarget(
23            self,
24            action: #selector(didTapButton(_:)),
25            for: .touchUpInside
26        )
27    }
28
29    @objc private func didTapButton(_ sender: UIButton) {
30        print("button tapped: \\(sender.currentTitle ?? \"\")")
31    }
32}

This is the basic answer for fully programmatic UIKit views.

Selector Signatures

You can use either of these method forms:

swift
@objc private func didTapButton() { }

or

swift
@objc private func didTapButton(_ sender: UIButton) { }

The second form is often more useful because you can inspect the sender, which matters when several buttons share one action method.

Multiple Buttons, One Action

If you want several buttons to call the same method, set distinguishing properties such as tag or compare button references directly.

swift
1let saveButton = UIButton(type: .system)
2saveButton.tag = 1
3saveButton.addTarget(self, action: #selector(handleButton(_:)), for: .touchUpInside)
4
5let deleteButton = UIButton(type: .system)
6deleteButton.tag = 2
7deleteButton.addTarget(self, action: #selector(handleButton(_:)), for: .touchUpInside)
8
9@objc private func handleButton(_ sender: UIButton) {
10    switch sender.tag {
11    case 1:
12        print("save")
13    case 2:
14        print("delete")
15    default:
16        break
17    }
18}

That keeps related user actions in one place without requiring Interface Builder outlets.

Removing or Replacing Actions

You can also remove a target-action pairing:

swift
actionButton.removeTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside)

That is helpful when buttons change behavior based on screen state. In many cases, though, it is cleaner to keep one action and switch behavior inside the handler.

SwiftUI Is Different

If you are using SwiftUI, the pattern is different. A SwiftUI Button takes an action closure directly:

swift
Button("Tap Me") {
    print("tapped")
}

So the addTarget pattern is specifically for UIKit, not SwiftUI.

Programmatic UI Usually Pairs With Auto Layout

Developers often discover target-action at the same time they move away from storyboards. In that setup, remember that event wiring is only one part of making the button usable. You still need to add the button to the hierarchy, set translatesAutoresizingMaskIntoConstraints = false when using Auto Layout, and activate constraints so the control actually appears where users can tap it.

Common Pitfalls

The most common mistake is forgetting @objc on the selector method. Without it, the selector cannot be resolved correctly at runtime.

Another issue is using the wrong control event. For normal taps, .touchUpInside is usually correct. Developers also sometimes forget to add the button to the view hierarchy or to set up layout constraints, then assume the action registration failed when the button was never visible or tappable in the first place.

Summary

  • In UIKit, register button actions with addTarget.
  • Use a selector method marked with @objc.
  • '.touchUpInside is the usual event for button taps.'
  • Include the sender parameter when one method handles multiple buttons.
  • This target-action pattern is for UIKit; SwiftUI uses closure-based actions instead.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.