inheritanceUIAlertController并遇到运行时错误

我不熟悉iOS和OSX的编程,并决定从Swift开始,使用iOS8 API作为testing应用程序,并尝试使用其他环境中使用的编程技术。 但是,我遇到了一个奇怪的情况,希望有人能够识别和帮助我。 这涉及UIAlertController子类的困难。

这是我第一次尝试:

import UIKit class FubarAlertController: UIAlertController { convenience init (message:String) { self.init(title: "Alert", message: message, preferredStyle: UIAlertControllerStyle.Alert); self.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)) } } 

但是,我在Xcode中得到了以下警告,我不明白 – 在我看来,这些错误在我看来是自相矛盾的(赦免坏的双关语)

 use of self in delegating initializer before self.init is called Self.init is't called on all paths in delegating initialiser 

所以然后我试了

 class FubarAlertController: UIAlertController { convenience init (message:String) { self.init(); self.title = "Alert"; self.message = message; self.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)) } } 

并没有遇到任何编译时错误。 但是,当我使用这样一个简单的ViewController像这样

 class FubarController: UIViewController { // method invoked when a UIBarButtonItem action takes place @IBAction func enterTextButtonAction(sender: UIBarButtonItem) { let controller = FubarAlertController(message: "Fubar!"); presentViewController(controller, animated: true, completion: nil); } } 

我得到了以下的运行时错误,我不太明白

 *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController (<UiToolKit.TextChangedAlertController: 0x7adf2340>) of style UIAlertControllerStyleActionSheet. The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.' 

但是,如果我只是简单地实现FubarAlertController而没有方法或属性,我可以将它看作是在界面生成器动作中的UIAlertController,就像这样

 class FubarController: UIViewController { // method invoked when a UIBarButtonItem action takes place @IBAction func enterTextButtonAction(sender: UIBarButtonItem) { let controller = FubarAlertController(title: "Alert", message: "Fubar!", preferredStyle: UIAlertControllerStyle.Alert); controller.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)) presentViewController(controller, animated: true, completion: nil); } } 

…一切都按预期工作 – 没有编译时间或运行时错误,但我不明白为什么!

所以我的问题是:

(i)为什么我不能以我第一次尝试的方式执行便捷初始化方法? 我在这里错过了什么魔法知识? 为什么我不能在方便初始化程序中在自己的上下文中调用超类init方法?

(ii)当我第二次执行UIAlertController的子类时,我怎么得到运行时间而不是编译时间错误呢?

非常感谢,使这个目前很远,期待一些反馈 – 我很难过!

我知道这是一个古老的问题,但认为它可以使用至less一个部分的答案。

(I)我不得不像你一样去获得UIAlertController的子类。 我认为简单的答案是“不要这样做”。 苹果在技术上不允许UIAlertController的子类化,按照他们的文档:

UIAlertController类旨在按原样使用,不支持子类。 这个类的视图层次是私有的,不能被修改。

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAlertController_class/

(二)我在iPad上运行我的iPhone应用程序时遇到了同样的错误。

 *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController of style UIAlertControllerStyleActionSheet. The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.' 

由于iPad上的popup窗口不是全屏,因此iPad需要设置sourceViewsourceRect属性来确定popup窗口的显示位置。

每当将样式设置为.ActionSheet时,将这样的代码添加到您的UIAlertController:

 //For iPad, check that there is a popover and set action button as the sender if let popoverController = controller.popoverPresentationController { //Sender will be a UIButton, cast down to UIView popoverController.sourceView = sender as? UIView popoverController.sourceRect = sender.bounds } 

根据您的情况,您可能需要调整它。 我上面的例子来自一个IBAction函数,其中sender是一个UIButton。