下面是我的代码:
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()?
任何想法?由于
注::基于Apple的文档:
指定初始化项必须从它的直接父类调用指定初始化项。"
这是否意味着在Swift中不允许继承UIAlertAction ?在Objective-C中这样做没有问题。
我想创建UIAlertAction子类的原因是因为我想添加一个ReactiveCocoa命令作为一个动作
解决方案实际上几乎肯定是使用类扩展。
extension UIAlertAction {
convenience init(title: String) {
self.init(title: title, style: .Default, handler: nil)
}
}
用法:
let okayAction = UIAlertAction(title: "Okay")
您仍然可以子类化UIAlertAction
以添加属性。子类仍然可以使用从UIAlertAction
类扩展而来的这个方便的初始化器。
最后,为了它的价值,有人已经创建了一个Reactive Cocoa UIAlertAction
子类。他们只是在Objective-C中做了。看到在项目中添加Objective-C没有害处,你可以采用这种方法……或者直接安装pod…
就像@nhgrif说的,使用extension
是要走的路。这是编写表达性代码的一种补充方式。
例子:
/// 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)
}))
我在研究同样的问题时看到了这篇文章。这篇文章已经发布好几年了,所以在这一点上可能对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
}
}
这样做的原因是,要么在子类中没有定义指定初始化项,要么来自超类的所有指定初始化项都被子类实现了。在这两种情况下,所有来自超类的便利初始化器都被继承下来(除了子类中具有匹配签名的任何初始化器)。这是从超类中调用方便初始化器的唯一方法,因为正如前面提到的,Init仅限于指定的初始化器。
因为在我的例子中没有任何指定初始化项的实现,所以子类也从父类继承了所有指定初始化项。因此,由于没有定义任何指定初始化式,超类中的所有初始化式都可用,就像它们在子类中定义一样。
在https://docs.swift.org/swift-book/LanguageGuide/Initialization.html的Swift书中有一篇关于初始化的完整文章。在这种情况下,特别感兴趣的是以下四个小节:
- 类类型的初始化委派:https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID219
- 两阶段初始化:https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID220
- 初始化继承和重写:https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID221
- 自动初始化继承:https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID222