UIAlertController — действие не выполняется, если оповещение отклонено в первый раз

В проекте, над которым я работаю, мне пришлось написать вспомогательный модуль UIAlert, который будет отображать всплывающие окна здесь и там в моем приложении для iOS. Всплывающие окна написаны как функции класса, которые я могу просто вызвать в любом месте кода (класс статичен, как и все функции).

Теперь я сталкиваюсь с очень странной ошибкой, когда вы отклоняете предупреждение один раз, а затем открываете его снова, его действия больше не работают (например, обработчик действий не вызывается). Это работает, если вы нажмете действие при первом отображении всплывающего окна, хотя...

Вот код конкретного всплывающего окна, для которого возникает эта ошибка (никаких других всплывающих окон это не затрагивает):

static func popSkipWalkthrough() {
    let alert = UIAlertController(title: "Skip", message: "whatever", preferredStyle: .Alert)

    alert.addAction(cancelAction)
    alert.addAction(skipWalkthroughAction)
    appDelegate.window!.rootViewController!.presentViewController(alert, animated: true, completion: nil)
}

skipWalkthroughAction определяется следующим образом:

static let skipWalkthroughAction = UIAlertAction(title: "Continue", style: .Default, handler: { (action: UIAlertAction!) -> Void in
    appDelegate.setWindowViewTo("NavCtrl", navigateTo: false)
    CallIn.Settings.didWalkthrough = true
})

И cancelAction определяется как:

static let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)

В частности, это всплывающее окно отображается каждый раз, когда вы нажимаете кнопку «пропустить» на последнем шаге пошагового руководства...

Я попробовал несколько версий о том, в чем причина такого поведения, и я думаю, что это может быть как-то связано с тем, что всплывающее окно на самом деле не освобождается, но на данный момент я совсем не уверен...

Любые идеи ?


person Skwiggs    schedule 09.02.2016    source источник


Ответы (1)


Несмотря на то, что у меня есть проблемы с тем, как закодирован этот многократно используемый фрагмент, эту проблему можно решить, отправив сообщение copy: на skipWalkthroughAction. Просто выполните:

static func popSkipWalkthrough() {
    let alert = UIAlertController(title: "Skip", message: "whatever", preferredStyle: .Alert)

    alert.addAction(cancelAction.copy() as! UIAlertAction)
    alert.addAction(skipWalkthroughAction.copy() as! UIAlertAction)
    appDelegate.window!.rootViewController!.presentViewController(alert, animated: true, completion: nil)
}

Это должно решить эту проблему.

Вы также можете решить эту проблему, переместив alert на уровень экземпляра. Тогда вам не нужно отправлять copy:.

Лучший подход

Если вы хотите «по-настоящему» многоразового использования UIAlertController, вам лучше создать расширение UIViewController. У меня есть это в одном из моих проектов:

extension UIViewController {
    func showAlertControllerWithTitle(title:String?,message:String?,actions:[UIAlertAction],dismissingActionTitle:String?, dismissBlock:(() -> ())?) -> UIAlertController {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
        if dismissingActionTitle != nil {
            let okAction = UIAlertAction(title: dismissingActionTitle, style: .Default) { (action) -> Void in
                dismissBlock?()
                alertController.dismissViewControllerAnimated(true, completion:nil)
            }
            alertController.addAction(okAction)
        }
        for action in actions {
            alertController.addAction(action)
        }
        self.presentViewController(alertController, animated: true, completion:nil)
        return alertController
    }
}
person avismara    schedule 09.02.2016
comment
Это исправило! Спасибо. Не могли бы вы также уточнить, почему у вас возникли проблемы с тем, как я это написал? Есть ли лучшее решение ? - person Skwiggs; 09.02.2016