对UIAlertController进行子类化并遇到运行时错误 [英] Subclassing UIAlertController and encountering runtime errors

查看:335
本文介绍了对UIAlertController进行子类化并遇到运行时错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是iOS和OSX编程的新手,并决定从Swift开始,将iOS8 API用于测试应用程序,并尝试在其他环境中使用的一些编程技术。但是,我遇到了一个奇怪的情况,我希望有人可以识别并帮助我。这涉及对UIAlertController进行子类化的困难。

I'm new to programming for iOS and OSX, and decided to start with Swift and use the iOS8 API's for a test app and attempt some programming techniques I use in other environments. However, I'm encountering a strange situation which I hope someone could identify and help me with. This involves difficulties subclassing 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中收到了以下警告,我不明白 - 在我看来,错误在我看来是自相矛盾的(原谅我的错误)惩罚)

However, I got the following warnings in Xcode, which I don't understand- to my eyes, the errors appear to me to be self contradictory (pardon the bad pun)

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使用它时

and did not encounter any compile time errors. However, when I use this from a simple ViewController like so

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

我再次遇到以下运行时错误,我不知道我完全理解

I get the following runtime error which again, I don't quite understand

*** 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

But, if I simply implement FubarAlertController with no methods or properties at all, I can call it exactly as if it were a UIAlertController in the interface builder action like so

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

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

... and everything works as expected - no compile time or run time errors but I don't understand why!

所以我的问题是:

(i为什么我不能以第一次尝试的方式实现方便的init方法?我在这里错过了什么神奇的知识?为什么我不能在便捷初始化器中调用self的上下文中的超类init方法?

(i) Why couldn't I implement the convenience init method in the manner of my first attempt? What magic knowledge am I missing here? Why couldn't I call a super class init method in the context of self within a convenience initialiser?

(ii)为什么我得到运行时间而不是编译时间当我第二次实现它时,我将UIAlertController子类化了吗?

(ii) How come I get run time as opposed to compile time errors when I subclass UIAlertController as I implemented it the second time?

非常感谢你做到这一点并期待一些反馈 - 我很难过!

Many thanks for making it this far and looking forward to some feedback - I'm stumped!

推荐答案

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

I know this is an old question, but thought it could use at least a partial answer.

(I)我必须像你一样做UIAlertController的子类。我认为简单的答案是不要这样做。 Apple技术上不允许UIAlertController的子类化,根据他们的文档:

(I) I've had to do the same as you to get a subclass of UIAlertController working. I think the simple answer is "Don't do it". Apple technically doesn't allow subclassing of UIAlertController, as per their documentation:


UIAlertController类旨在按原样使用不支持子类化。此类的视图层次结构是私有的,不得修改。

The UIAlertController class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

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

(II)
在iPad上运行我的iPhone应用程序时出现同样的错误。

(II) I got this same error when running my working iPhone app on iPad.

*** 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上的弹出框不是全屏,iPad需要 sourceView sourceRect 属性设置用于确定弹出框应该在屏幕上显示的位置。

Since a popover on iPad is not full screen, iPad needs the sourceView or sourceRect property set to determine where on screen the popover should show from.

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

Add some code like this to your UIAlertController whenever you set the style to .ActionSheet:

//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。

You may have to tweak this, depending your situation. My example above came from a IBAction function where sender is a UIButton.

这篇关于对UIAlertController进行子类化并遇到运行时错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆