mattdipasquale mattdipasquale - 1 year ago 171
Swift Question

extension UIAlertController convenience init warning

When I define a

convenience initializer:

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

and use it in a button action in my subclass of

func buttonAction(button: UIButton) {
let alert = UIAlertController(dictionary: nil, error: nil, handler: nil)
presentViewController(alert, animated: true, completion: nil)

and click that button on the Simulator, I get a warning:

Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (UIAlertController)

However, I don't get a warning if instead of a convenience initializer, I use a global function:

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

I've reported this to Apple as an iOS SDK bug.

Until it's fixed, is it OK to ignore the warning and use the convenience initializer?


I noticed the same issue with convenience initializers. It's actually two bugs at once.

  1. Swift allocates a UIAlertController instance.
  2. Swift calls your convenience init with the instance created by Swift.
  3. There you call UIKit's convenience init, which is actually the Objective-C factory method +(id) alertControllerWithTitle:message:preferredStyle:.
  4. There UIKit allocates its own UIAlertController instance. (Bug #1)
  5. UIKit sets up its own instance.
  6. UIKit deallocates your Swift instance.
  7. UIAlertController's deinit (dealloc) accesses the view property which leads to the log message. (Bug #2)
  8. Control comes back to your own convenience init where self silently changed from Swift's UIAlertController instance to the one from UIKit.
  9. Everything you do now happens on the instance created by UIKit which is fine.

So the first bug is that Swift creates a temporary UIAlertController which is destroyed without ever being used.

The second bug is that UIViewController accesses the view property during deinitialization which it shouldn't.

Regarding your question:
Both bugs shouldn't be problematic so we can simply ignore the warning for now. I do that too and there weren't any problems yet - just that warning in the log.