如何编写通用的Swift类函数以使用闭包初始化类?

时间:2019-06-05 17:50:18

标签: swift generics self initializer

我正在尝试为Swift类编写一个通用类函数,该函数将允许我使用尾随闭包语法来初始化类。

我已经使其适用于特定的类,例如UILabel。

// Extension for UILabel
extension UILabel {
    class func new(_ initialization: (inout UILabel) -> Void) -> UILabel {
        var label = UILabel()
        initialization(&label)
        return label
    }
}

// Initialize new UILabel using trailing closure syntax and "new" function
let label = UILabel.new {
    $0.textColor = .red
}

但是,我希望对NSObject的所有子类都具有此功能,因此我试图实现上述“新”功能的通用版本。到目前为止,我已经提出了这个建议:

extension NSObject {
    class func new(_ initialization: (inout Self) -> Void) -> Self {
        var newSelf = Self()
        initialization(&newSelf)
        return newSelf
    }
}

但这会产生以下错误:'Self'仅在协议中可用,或者作为类中方法的结果可用;您是说'NSObject'吗?

我正在使用Swift 5.1(Xcode 11 beta)在操场上尝试这种操作。

1 个答案:

答案 0 :(得分:1)

正如 Hamish 所说,也许最好将init放在外面,这样更灵活。但是,使用协议可以对此采取一种解决方法。

protocol Initializable {
    init()
}

extension Initializable {
    static func new(_ initialization: (inout Self) -> Void) -> Self {
        var newSelf = Self()
        initialization(&newSelf)
        return newSelf
    }
}

extension NSObject: Initializable {}

NSObject已经有一个init,因此它自动符合Initializable。 然后在协议上写您的扩展名。

唯一需要注意的是,您现在无法使用class修饰符,就像您在protocol中一样。

不确定NS_UNAVAILABLE修饰符是否会导致问题,我认为当在隐藏init的类上使用它时,它可能在运行时崩溃。