Как создать кнопку программно (через код) в Swift для iOS?
Полное руководство: создание UIButton программно в Swift
Давайте разберем создание кнопки от простого к сложному. Вы уже почти всё сделали правильно, но забыли самое главное — добавить обработчик нажатия (target-action).
Базовый пример с обработчиком
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
createButton()
}
private func createButton() {
let button = UIButton(type: .system) // используем системный тип
button.setTitle("Нажми меня", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .systemBlue
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
button.layer.cornerRadius = 12
button.clipsToBounds = true
// Добавляем обработчик нажатия
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
// Размещаем кнопку (пока статически)
button.frame = CGRect(x: 50, y: 200, width: 250, height: 50)
view.addSubview(button)
}
@objc private func buttonTapped() {
print("Кнопка нажата!")
// Здесь можно показать alert или выполнить действие
let alert = UIAlertController(title: "Привет!", message: "Кнопка работает", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
}
Ключевые моменты:
- button.addTarget(self, action: #selector(...), for: .touchUpInside) — это связка кнопки с методом.
self— это ViewController, который будет обрабатывать нажатие. - @objc — обязательная аннотация перед методом, так как target-action использует Objective-C runtime.
- .touchUpInside — стандартное событие для кнопки (нажали и отпустили внутри).
Продвинутый пример с Auto Layout и кастомным стилем
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupModernButton()
}
private func setupModernButton() {
let button = UIButton(type: .custom)
button.setTitle("Продвинутая кнопка", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = UIColor(red: 0.2, green: 0.5, blue: 0.9, alpha: 1.0)
button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
// Кастомизация внешнего вида
button.layer.cornerRadius = 16
button.layer.shadowColor = UIColor.black.cgColor
button.layer.shadowOffset = CGSize(width: 0, height: 4)
button.layer.shadowOpacity = 0.3
button.layer.shadowRadius = 6
button.clipsToBounds = false
button.contentEdgeInsets = UIEdgeInsets(top: 12, left: 24, bottom: 12, right: 24)
// Добавляем иконку (SF Symbol)
button.setImage(UIImage(systemName: "star.fill"), for: .normal)
button.tintColor = .white
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 8)
button.addTarget(self, action: #selector(modernButtonTapped), for: .touchUpInside)
// Auto Layout
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
button.heightAnchor.constraint(equalToConstant: 50)
])
}
@objc private func modernButtonTapped() {
print("Кнопка нажата!")
// Анимация нажатия
UIView.animate(withDuration: 0.1) {
// Можно изменить alpha или transform для тактильного отклика
}
}
}
Работа с состояниями кнопки
У UIButton есть несколько состояний: .normal, .highlighted, .disabled, .selected. Вы можете задавать разные стили для каждого:
button.setTitleColor(.lightGray, for: .disabled)
button.setTitleColor(.darkGray, for: .highlighted)
button.setBackgroundImage(UIImage(named: "bg_highlighted"), for: .highlighted)
Почему не работал ваш код?
Вы не добавили addTarget — это самая частая ошибка новичков. Без этого кнопка существует визуально, но не реагирует на касания. Также рекомендую использовать UIButton(type: .system) — он автоматически обрабатывает выделение текста при нажатии.
Советы для разных экранов
- Используйте Auto Layout (через
NSLayoutConstraint) вместоframe— это адаптирует кнопку под любой размер экрана. - Для отступов слева/справа используйте привязку к safe area:
button.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20) - Высоту кнопки лучше задавать фиксированной (44–50 pt — рекомендация Apple для удобного нажатия пальцем).
Альтернативный подход: создание кнопки через замыкание (без @objc)
Если вы не хотите использовать @objc и target-action, можно создать простую обёртку на замыканиях. Это более современный и безопасный способ, который не требует указания селекторов:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupClosureButton()
}
private func setupClosureButton() {
let button = ClosureButton(type: .system)
button.setTitle("Кнопка с closure", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .systemGreen
button.layer.cornerRadius = 12
button.frame = CGRect(x: 50, y: 300, width: 250, height: 50)
button.tapHandler = {
print("Кнопка нажата через closure!")
// Выполняем действие
}
view.addSubview(button)
}
}
// Вспомогательный класс
class ClosureButton: UIButton {
var tapHandler: (() -> Void)?
override init(frame: CGRect) {
super.init(frame: frame)
addTarget(self, action: #selector(handleTap), for: .touchUpInside)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func handleTap() {
tapHandler?()
}
}
Дополнительные рекомендации
- Используйте UIButton.Configuration (iOS 15+) — это новый API, который упрощает настройку кнопок с иконками, отступами и стилями.
- Для простых проектов можно создать extension для UIButton, который добавляет метод с замыканием — это уменьшит дублирование кода.
- Не забывайте про accessibilityIdentifier — это поможет в UI-тестах.