Avatar ·

Как создать UIAlertView в Swift? (iOS, UIKit)

Я только начал изучать Swift и iOS-разработку. Пишу свое первое приложение — простой список задач. Хочу показывать всплывающее предупреждение (alert) при попытке удалить задачу, чтобы пользователь подтвердил действие.

В старых туториалах я вижу UIAlertView с делегатами и инициализатором вроде:


let alert = UIAlertView(title: "Внимание", message: "Вы уверены?", delegate: self, cancelButtonTitle: "Нет", otherButtonTitles: "Да")
alert.show()

Но Xcode подчеркивает UIAlertView красным и пишет, что он устарел в iOS 9. Я использую Xcode 14 и iOS 16. Как правильно показывать всплывающие окна в современном Swift? Нужен пример с кнопками и обработкой нажатий.

Мой текущий код (который не работает):


import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        showDeleteAlert()
    }
    
    func showDeleteAlert() {
        let alert = UIAlertView(title: "Удалить?", message: "Это действие нельзя отменить", delegate: self, cancelButtonTitle: "Отмена", otherButtonTitles: "Удалить")
        alert.show()
    }
}

Подскажите, как это исправить для современного Swift?

<<>>

Используйте UIAlertController вместо устаревшего UIAlertView

В современном Swift (iOS 8 и новее) для отображения всплывающих предупреждений используется UIAlertController. Он заменил UIAlertView и UIActionSheet, предоставляя единый, более гибкий интерфейс.

Базовый пример: Alert с двумя кнопками


import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Вызовем alert через небольшую задержку для демонстрации
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.showDeleteAlert()
        }
    }
    
    func showDeleteAlert() {
        // 1. Создаем UIAlertController с нужным стилем
        let alertController = UIAlertController(
            title: "Удалить задачу?",
            message: "Это действие нельзя отменить.",
            preferredStyle: .alert
        )
        
        // 2. Создаем кнопку "Отмена" (стиль .cancel — она будет жирной и внизу)
        let cancelAction = UIAlertAction(title: "Отмена", style: .cancel) { _ in
            print("Пользователь нажал Отмена")
        }
        
        // 3. Создаем кнопку "Удалить" (стиль .destructive — красная, для опасных действий)
        let deleteAction = UIAlertAction(title: "Удалить", style: .destructive) { _ in
            print("Пользователь подтвердил удаление")
            // Здесь ваш код удаления задачи
        }
        
        // 4. Добавляем кнопки в контроллер
        alertController.addAction(cancelAction)
        alertController.addAction(deleteAction)
        
        // 5. Показываем alert
        present(alertController, animated: true, completion: nil)
    }
}

Разбор ключевых моментов:

  • preferredStyle — может быть .alert (всплывающее окно по центру экрана) или .actionSheet (панель снизу).
  • UIAlertAction — каждая кнопка. У нее есть три стиля: .default (обычная), .cancel (отмена, жирный шрифт), .destructive (опасное действие, красный цвет).
  • Обработка нажатия — через замыкание (closure) в инициализаторе UIAlertAction. Не нужно реализовывать делегаты, как в старом UIAlertView.
  • present — метод для отображения контроллера. Работает на любом UIViewController.

Добавление текстового поля (например, для ввода имени задачи)

Если нужно попросить пользователя ввести текст (например, переименовать задачу), добавьте addTextField:


func showRenameAlert() {
    let alertController = UIAlertController(title: "Переименовать задачу", message: "Введите новое название", preferredStyle: .alert)
    
    alertController.addTextField { textField in
        textField.placeholder = "Название задачи"
        textField.text = "Текущее название"
    }
    
    let saveAction = UIAlertAction(title: "Сохранить", style: .default) { _ in
        guard let textField = alertController.textFields?.first, let newName = textField.text, !newName.isEmpty else {
            return
        }
        print("Новое название: \(newName)")
        // Обновляем задачу
    }
    
    let cancelAction = UIAlertAction(title: "Отмена", style: .cancel)
    
    alertController.addAction(saveAction)
    alertController.addAction(cancelAction)
    present(alertController, animated: true)
}

Распространенные ошибки новичков:

  • Забывают вызвать present — alert не покажется.
  • Пытаются использовать UIAlertView — он недоступен в iOS 13+ и вызовет ошибку компиляции.
  • Не проверяют текст из текстового поля на пустоту — может привести к крашу.
  • Пытаются показать alert до того, как view controller загрузился — лучше вызывать в viewDidAppear или позже.

Теперь ваш код будет работать на всех устройствах с iOS 8 и новее. Удачи в разработке!

<<>>

Альтернативный подход: использование UIAlertController с ActionSheet

Иногда вместо всплывающего окна по центру удобнее показать панель снизу (ActionSheet) — например, для выбора действий над элементом списка.


func showActionSheetForTask(at index: Int) {
    let actionSheet = UIAlertController(
        title: "Действия с задачей",
        message: "Выберите опцию",
        preferredStyle: .actionSheet  // вместо .alert
    )
    
    let editAction = UIAlertAction(title: "Редактировать", style: .default) { _ in
        print("Редактируем задачу \(index)")
    }
    
    let deleteAction = UIAlertAction(title: "Удалить", style: .destructive) { _ in
        print("Удаляем задачу \(index)")
    }
    
    let cancelAction = UIAlertAction(title: "Отмена", style: .cancel)
    
    actionSheet.addAction(editAction)
    actionSheet.addAction(deleteAction)
    actionSheet.addAction(cancelAction)
    
    // Для iPad нужно указать источник отображения (popover)
    if let popoverController = actionSheet.popoverPresentationController {
        popoverController.sourceView = self.view
        popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
        popoverController.permittedArrowDirections = []
    }
    
    present(actionSheet, animated: true)
}

Важно для iPad: ActionSheet на iPad отображается как popover, поэтому обязательно настройте popoverPresentationController, иначе приложение упадет с exception. На iPhone это не требуется — панель появляется снизу.

Выбор между .alert и .actionSheet зависит от контекста: для подтверждения опасных действий (удаление) лучше .alert, для выбора из нескольких опций (редактировать/удалить/поделиться) — .actionSheet.