UIAlertController extension convenience initialization warning

When I define the UIAlertController convenience UIAlertController :

 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 the button action in my subclass of UIViewController :

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

and press this button on the simulator, I get a warning:

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

However, I do not receive 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 reported this to Apple as an SDK error for iOS.

Until it is fixed, is it okay to ignore the warning and use the convenience initializer?

+6
source share
2 answers

I noticed the same problem with convenience initializers. These are actually two mistakes at once.

  • Swift allocates an instance of UIAlertController .
  • Swift invokes your convenience of init with an instance created by Swift.
  • There you call UIKit the convenience of init, which is actually the Objective-C factory method +(id) alertControllerWithTitle:message:preferredStyle:
  • There, UIKit allocates its own instance of UIAlertController . (error number 1)
  • UIKit installs its own instance.
  • UIKit frees up your Swift instance.
  • UIAlertController deinit (dealloc) accesses the view property, which results in a log message. (error number 2)
  • The control returns to your own convenience of init, where self silently changed from a Swift instance of UIAlertController to an instance from UIKit.
  • Everything you do now happens on the instance created by UIKit, which is fine.

Thus, the first mistake is that Swift creates a temporary UIAlertController that is destroyed without use.

The second error is that the UIViewController gains access to the view property during de-initialization, which should not be.


Regarding your question:
Both errors should not be problematic, so we can simply ignore this warning. I do it too, and there were no problems - it's just a warning in the log.

+10
source

I also faced the same problem

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

So, I moved on to an alternative path for this.

  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); } } } 

call this method in your ViewController as

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

All Articles