一尘不染

如何在Swift中编写通用的apply()函数?

swift

有什么办法可以使以下在Swift 3中正常工作?

 let button = UIButton().apply {
        $0.setImage(UIImage(named: "UserLocation"), for: .normal)
        $0.addTarget(self, action: #selector(focusUserLocation), 
                     for: .touchUpInside)
        $0.translatesAutoresizingMaskIntoConstraints = false
        $0.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        $0.layer.cornerRadius = 5
     }

apply<T>功能应该采取型的封闭(T)->Void,运行它传递self到它,然后简单地返回self

另一个选择是为此使用运算符,例如“
=>”(从Kotlin和Xtend语言中借用了这个想法)。

试图做这样的扩展NSObject

extension NSObject {   
    func apply<T>(_ block: (T)->Void) -> T
    {
        block(self as! T)
        return self as! T
    }
}

但是它需要在闭包中显式声明参数类型:

let button = UIButton().apply { (it: UIButton) in
        it.setImage(UIImage(named: "UserLocation"), for: .normal)
        it.addTarget(self, action: #selector(focusUserLocation), 
                     for: .touchUpInside)
        ...

这不方便,并且使整个想法不值得付出努力。类型已经在对象创建时指定,并且应该有可能不明确地重复它。

谢谢!


阅读 416

收藏
2020-07-07

共1个答案

一尘不染

HasApply协议

首先让我们定义HasApply协议

protocol HasApply { }

和相关扩展

extension HasApply {
    func apply(closure:(Self) -> ()) -> Self {
        closure(self)
        return self
    }
}

接下来让make NSObject符合HasApply

extension NSObject: HasApply { }

而已

让我们测试一下

let button = UIButton().apply {
    $0.titleLabel?.text = "Tap me"
}

print(button.titleLabel?.text) // Optional("Tap me")

注意事项

我不会使用NSObject(这是Objective-C处事方式的一部分,我认为将来会在某些时候删除它)。我更喜欢类似的东西UIView

extension UIView: HasApply { }
2020-07-07