5

这是我的代码:

class CustomAlertAction: UIAlertAction {
    init(title : String) {
        super.init(title: title, style: UIAlertActionStyle.Default) { (action) -> Void in
        }
    }
}

但是我得到了以下编译错误:

必须调用超类“UIAlertAction”的指定初始化程序

我知道 UIAlertAction 的指定初始化程序是 init()。但是 UIAlert 的 init(title, style, handler) 不会调用它指定的初始化器 init() 吗?

任何想法?谢谢

PS:基于苹果的文档:

指定初始化器必须从其直接超类中调用指定初始化器。”

这是否意味着不允许在 Swift 中继承 UIAlertAction?在 Objective-C 中这样做是没有问题的。

我之所以要创建 UIAlertAction 的子类,是因为我想添加一个 ReactiveCocoa 命令作为操作。

4

3 回答 3

9

解决方案实际上几乎可以肯定是使用类扩展来代替。

extension UIAlertAction {
    convenience init(title: String) {
        self.init(title: title, style: .Default, handler: nil)
    }
}

用法:

let okayAction = UIAlertAction(title: "Okay")

您仍然可以将其子类化UIAlertAction以向其添加属性。子类仍然可以使用您从类中扩展的便利初始化程序UIAlertAction


最后,值得一提的是,有人已经创建了一个 Reactive CocoaUIAlertAction子类。他们只是在Objective-C中做到了。看到将Objective-C添加到您的项目没有任何害处,您可以采用这种方法......或者只是安装那个pod......

于 2015-07-15T00:27:09.190 回答
1

就像@nhgrif所说,使用 anextension是要走的路。这是编写表现力代码的一种补充方式。

例子:

/// App alert actions
extension UIAlertAction {
    static var cancel: UIAlertAction {
        return UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
    }
    class func sharePhoto(handler: ((UIAlertAction) -> Void)?) -> UIAlertAction {
        return UIAlertAction(title: "Share", style: .Default, handler: handler)
    }
}

像这样使用它

alertController.addAction(.cancel)

alertController.addAction(.sharePhoto({ action in
    print(action)
}))
于 2016-10-28T19:58:45.393 回答
0

我在研究同样的问题时遇到了这篇文章。自发布以来已经有几年了,因此此时可能对 OP 没有帮助,但适用于任何搜索此问题的人。

看到这篇文章后,我做了一些进一步的研究。事实证明,至少在撰写本文时使用的 Swift 版本可以使用自定义 init 子类化 UIAlertAction。无论如何,我都会像直接针对 OP 一样回答。

您需要将您的 init 定义为便利 init,而您当前调用的 super.init 也是便利 init。只能在超类上调用指定的初始化程序(因此出现错误)。我还想在我的用例中引用操作附加到的 UIAlertController,所以我也有一个实例变量在使用。我也在这里使用我自己的 UIAlertController 子类。

class MyAlertAction: UIAlertAction {
    var alertController: MyAlertController? = nil

    convenience init(
        alertController: MyAlertController,
        title: String?,
        style: UIAlertAction.Style,
        handler: ((UIAlertAction) -> Void)?
    ) {
        // init must be called before instance variables and functions are referenced
        self.init(title: title, style: style, handler: handler)
        self.alertController = alertController
    }
}

这样做的原因是因为在子类中没有定义指定的初始化器,或者来自超类的所有指定的初始化器都已由子类实现。在这两种情况下,所有来自超类的便利初始化器都被继承下来(除了在子类中具有匹配签名的任何东西)。这是从超类调用便利初始化程序的唯一方法,因为如前所述,super.init 仅限于指定的初始化程序。

因为在我的示例中没有任何指定初始化程序的实现,所以子类也从超类继承所有指定初始化程序。因此,通过不定义任何指定的初始化器,超类中的所有初始化器都可用,就好像它们在子类中定义一样。

在https://docs.swift.org/swift-book/LanguageGuide/Initialization.html上的 Swift 书中有一整篇关于初始化的文章。在这种情况下特别感兴趣的是这四个小节:

  1. 类类型的初始化器委托:https ://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID219
  2. 两阶段初始化:https ://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID220
  3. 初始化器继承和覆盖:https ://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID221
  4. 自动初始化器继承:https ://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID222
于 2021-03-21T20:29:26.183 回答