扩展UIAlertController方便初始化警告

时间:2015-11-19 13:23:57

标签: ios swift initialization warnings uialertcontroller

当我定义UIAlertController便利初始值设定项时:

extension UIAlertController {
    convenience init(message: String?) {
        self.init(title: nil, message: message, preferredStyle: .Alert)
        self.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
    }
}

并在我的UIViewController

子类中的按钮操作中使用它
func buttonAction(button: UIButton) {
    let alert = UIAlertController(dictionary: nil, error: nil, handler: nil)
    presentViewController(alert, animated: true, completion: nil)
}

然后单击模拟器上的那个按钮,我收到一条警告:

  

不允许在取消分配时尝试加载视图控制器的视图,并且可能导致未定义的行为(UIAlertController)

但是,如果不使用便捷初始化程序,我不会收到警告,而是使用全局函数:

func UIAlertControllerWithDictionary(message: String?) -> UIAlertController {
    let alert = UIAlertController(title: nil, message: message, preferredStyle: .Alert)
    alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
    return alert
}

我已将此报告给Apple作为iOS SDK错误。

在修复之前,可以忽略警告并使用便利初始化程序吗?

2 个答案:

答案 0 :(得分:9)

我注意到便利初始化器存在同样的问题。 它实际上是两个错误。

  1. Swift分配s = s.replace("/","") 个实例。
  2. Swift使用Swift创建的实例调用您的便利init。
  3. 你打电话给UIKit的便利init,实际上是Objective-C工厂方法UIAlertController
  4. UIKit会分配自己的+(id) alertControllerWithTitle:message:preferredStyle:实例。 (Bug#1)
  5. UIKit设置了自己的实例。
  6. UIKit释放你的Swift实例。
  7. UIAlertController' s UIAlertController(dealloc)访问导致日志消息的deinit属性。 (Bug#2)
  8. Control返回到您自己的方便init,其中view默默地从Swift的self实例更改为来自UIKit的实例。
  9. 你现在所做的一切都发生在UIKit创建的实例上,没问题。
  10. 所以第一个错误是Swift创建了一个临时的UIAlertController,它在不被使用的情况下被销毁。

    第二个错误是UIAlertController在取消初始化期间访问UIViewController属性,它不应该这样做。

    关于你的问题:
    这两个错误都不会有问题所以我们现在可以简单地忽略这个警告。我这样做也没有任何问题 - 只是日志中的警告。

答案 1 :(得分:2)

我也面临同样的问题

  

不允许在取消分配时尝试加载视图控制器的视图,并且可能导致未定义的行为(UIAlertController)

所以我为此采取了替代方式。

 import UIKit
import Foundation

//the show alert function for failure
func showAlertforNetworkFailure(alerttitle :String, alertmessage: String,ButtonTitle: String, viewController: UIViewController)
{


    let alertController = UIAlertController(title: alerttitle, message: alertmessage, preferredStyle: .Alert)
    let okButtonOnAlertAction = UIAlertAction(title: ButtonTitle, style: .Default)
        { (action) -> Void in
            //what happens when "ok" is pressed

    }
    alertController.addAction(okButtonOnAlertAction)
    alertController.show()



}

// function for show alert in Main View Controller
extension UIAlertController {

    func show() {
        present(true, completion: nil)
    }

    func present(animated: Bool, completion: (() -> Void)?) {
        if let rootVC = UIApplication.sharedApplication().keyWindow?.rootViewController {
            presentFromController(rootVC, animated: animated, completion: completion)
        }
    }

    private func presentFromController(controller: UIViewController, animated: Bool, completion: (() -> Void)?) {
        if let navVC = controller as? UINavigationController,
            let visibleVC = navVC.visibleViewController {
                presentFromController(visibleVC, animated: animated, completion: completion)
        }  else {
                controller.presentViewController(self, animated: animated, completion: completion);
        }
    }
}

在ViewController中将此方法称为

showAlertforNetworkFailure("Server Error!!!", alertmessage: "Server does not responding,please Try in later.", ButtonTitle: "Okay", viewController: self)