在Swift中继承UIAlertAction



下面是我的代码:

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书中有一篇关于初始化的完整文章。在这种情况下,特别感兴趣的是以下四个小节:

  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

最新更新