Delegate в Swift

Давайте рассмотрим более подробный пример использования делегатов в iOS, чтобы лучше понять, как это работает на практике. Мы создадим простое приложение с двумя контроллерами: один контроллер будет представлять экран с кнопкой, а другой контроллер будет выполнять некоторые действия, когда кнопка будет нажата.
Полный пример использования делегатов:
Шаг 1: Определение протокола
Протокол — это "контракт", который описывает, какие методы должен реализовать класс, чтобы стать делегатом. В нашем случае протокол будет содержать один метод, который будет вызван при нажатии кнопки.
protocol ButtonDelegate: AnyObject {
func didPressButton()
}
Шаг 2: Создание первого контроллера (с кнопкой)
Первый контроллер будет содержать кнопку, и когда пользователь нажимает на эту кнопку, он будет уведомлять делегата о том, что произошло событие.
import UIKit
class ButtonViewController: UIViewController {
// Свойство делегата
weak var delegate: ButtonDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Настраиваем кнопку
let button = UIButton(type: .system)
button.setTitle("Нажми меня", for: .normal)
button.frame = CGRect(x: 100, y: 100, width: 200, height: 50)
button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
view.addSubview(button)
view.backgroundColor = .white
}
// Метод, который будет вызван при нажатии кнопки
@objc func buttonPressed() {
// Уведомляем делегата о том, что кнопка была нажата
delegate?.didPressButton()
}
}
Шаг 3: Создание второго контроллера (делегата)
Второй контроллер будет принимать на себя роль делегата и реализовывать метод didPressButton
, чтобы обрабатывать событие нажатия кнопки.
import UIKit
class AnotherViewController: UIViewController, ButtonDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let buttonVC = ButtonViewController()
buttonVC.delegate = self // Назначаем делегата
// Добавляем контроллер с кнопкой как дочерний контроллер
addChild(buttonVC)
view.addSubview(buttonVC.view)
buttonVC.didMove(toParent: self)
view.backgroundColor = .lightGray
}
// Реализация метода делегата
func didPressButton() {
print("Кнопка нажата во втором контроллере")
// Допустим, мы показываем алерт при нажатии кнопки
let alert = UIAlertController(title: "Уведомление", message: "Кнопка была нажата", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "ОК", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
}
}
Подробное объяснение:
-
Протокол
ButtonDelegate
:- Протокол описывает метод, который должен реализовать любой делегат (в нашем случае это
didPressButton
). - Мы используем модификатор
AnyObject
, чтобы делегат мог быть слабым (weak
), что помогает избежать циклов удержания.
- Протокол описывает метод, который должен реализовать любой делегат (в нашем случае это
-
Контроллер с кнопкой (
ButtonViewController
):- Этот контроллер содержит кнопку и свойство
delegate
, которое ссылается на объект, реализующий протоколButtonDelegate
. - Когда кнопка нажата, вызывается метод
delegate?.didPressButton()
, если делегат установлен.
- Этот контроллер содержит кнопку и свойство
-
Контроллер делегата (
AnotherViewController
):- Этот контроллер реализует протокол
ButtonDelegate
и содержит методdidPressButton
, который вызывается, когда кнопка в другом контроллере нажата. - Здесь мы показываем алерт при срабатывании метода делегата.
- Этот контроллер реализует протокол
Почему это полезно:
- Гибкость: Делегаты позволяют вам отделить логику обработки событий от их источника. Это полезно, когда один объект должен передать управление другому объекту.
- Модульность: Использование делегатов помогает сделать код более модульным и переиспользуемым.
- Отсутствие жесткой связи: Делегаты позволяют передавать события между объектами без необходимости их тесного связывания, что улучшает тестируемость и расширяемость кода.
Как избежать циклов удержания:
Важно помнить о слабых ссылках (weak
) при использовании делегатов, так как это помогает предотвратить циклы удержания, где два объекта удерживают друг друга и никогда не освобождаются из памяти. В примере выше мы используем:
Давай рассмотрим более подробный пример использования делегатов в iOS, чтобы лучше понять, как это работает на практике. Мы создадим простое приложение с двумя контроллерами: один контроллер будет представлять экран с кнопкой, а другой контроллер будет выполнять некоторые действия, когда кнопка будет нажата.
weak var delegate: ButtonDelegate?
Эта строка гарантирует, что ButtonViewController
не будет удерживать своего делегата, что особенно важно в долгоживущих иерархиях контроллеров.
Дополнительные варианты использования:
- UITableView и UICollectionView: Встроенные делегаты используются для управления действиями в таблицах и коллекциях.
- Custom Views: Делегаты могут использоваться для передачи событий от пользовательских компонентов (например, кастомных кнопок или слайдеров) к контроллеру.