【问题标题】:How can I override convenience init in UIAlertController for swift?如何快速覆盖 UIAlertController 中的便利初始化?
【发布时间】:2026-01-28 07:40:01
【问题描述】:

我正在尝试覆盖 UIAlertController 中的便捷初始化,但它给了我一个错误,例如“初始化程序不会覆盖其超类中的指定初始化程序”。 如何使用继承或扩展来覆盖它? 我的代码如下。

import UIKit

class ColorAlertViewController: UIAlertController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

    }

    override convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, colorCode: String?){
        super.init(title: title, message: message, preferredStyle: preferredStyle)
    }
}

【问题讨论】:

    标签: ios swift uialertcontroller


    【解决方案1】:

    您没有覆盖任何便利 init,看起来您正在创建一个新的。

    convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, colorCode: String?){
        self.init(title: title, message: message, preferredStyle: preferredStyle)
    }
    

    可能是你想要的,你只需要处理颜色代码

    看来您将不得不绕道而行:

    首先创建一个创建扩展

    extension UIAlertController
    {
    
        class func create(title: String?, message: String?, preferredStyle: UIAlertControllerStyle) -> AnyObject
        {
            return UIAlertController(title: title, message: message, preferredStyle: preferredStyle);
        }
    }
    

    然后在 ColorAlertViewController 中,你将创建另一个函数来创建这个对象:

    class func createWithColor(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, colorCode: String?) -> AnyObject
    {
        var c = super.create(title, message: message, preferredStyle: preferredStyle);
        //handle color code here
        return c;
    }
    

    现在你想在任何地方创建这个对象,只需调用

    var colorAlertView = ColorAlertViewController.createWithColor("title Name", message: "the message", preferredStyle: .ActionSheet, colorCode: "the color");
    

    当然,这在 UI builder 中不起作用,您必须通过代码创建它。

    【讨论】:

    • 这导致错误:Use of 'self' in delegating initializer before self.init is calledSelf.init isn't called on all paths in delegating initializer
    • 非常感谢!你是我的救命恩人! @skyline75489 我们必须在 'self.init(~~~~)' 行上方插入 'self.init()'。 :D
    • 看起来你不能快速完成,奇怪的是它在操场上对我有用。 developer.apple.com/library/prerelease/ios/documentation/swift/…
    • @RubyAn 对不起,兄弟。 Override 似乎是不行的。也许你应该考虑这个答案。
    【解决方案2】:

    您确实应该将其包装在一个类中而不是覆盖。这样你的包装类就可以执行对调用者隐藏的活动。

    Apple 明确声明 UIAlertViewController 不能继承自:

    重要

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

    实施:

    extension UIAlertController
    {
        class func create(title: String?, message: String?, preferredStyle: UIAlertControllerStyle) -> AnyObject
        {
            return UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert);
        }
    }
    
    class ColorAlertController {
        private var alertController: UIAlertController!
    
        private init() {
        }
    
        public convenience init(title: String?, message: String?, initialValue: T) {
            self.init()
            alertController = UIAlertController.createAlert(title: title, message: message)
            ... do color stuff ...
        }
    }
    

    ColorAlertController 还可以包含一些模态表示功能。

    func present(inViewController controller: UIViewController) {
        controller.present(alertController, animated: true)
    }
    

    您可以通过将 UIAlertControllers 包装在像这样的自定义模态控制器中来做一些非常酷的事情。剩下的魔法由你决定。

    【讨论】:

      【解决方案3】:

      似乎没有办法做到这一点“覆盖”。

      根据这个answer,您似乎需要在添加自定义init之前“覆盖”原点init

      class ColorAlertViewController: UIAlertController {
      
          override func viewDidLoad() {
              super.viewDidLoad()
          }
      
          override func didReceiveMemoryWarning() {
              super.didReceiveMemoryWarning()
      
          }
      
          convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle) {
              self.init(title: title, message: message, preferredStyle:preferredStyle)
          }
      
          convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, colorCode: String?){
              self.init(title: title, message: message, preferredStyle: preferredStyle)
              // handle colorCode
          }
      
      }
      

      此代码没有编译错误。但是,这会导致运行时出现无限循环。

      【讨论】:

      • 感谢您的回复。当我尝试这段代码时,它发生了 exc_bad_access 错误。它看起来像 infinity 调用 init 方法。
      • 现在我开始认为这可能是一个错误。
      • 我更新了我的答案,它在操场上工作,但它不会很快工作,因为方便 init 需要委托 init,所以我发布了一个解决方法
      • @Knight0fDragon 解决方法没问题。我仍然认为这是 Swift 的某种问题。 UIAlertController 没有任何指定的初始化器,这会导致这个问题。
      • 我发布了一个链接,解释它是故意的,在我的答案的链接中查找这张图片:developer.apple.com/library/prerelease/ios/documentation/Swift/… Apple 可能不希望 UIAlertController 被自定义 init 子类化,谁知道呢。