Ios 如何在Swift中编写泛型apply()函数?

Ios 如何在Swift中编写泛型apply()函数?,ios,swift,functional-programming,Ios,Swift,Functional Programming,是否有任何方法可以在Swift 3中实现以下功能 let button = UIButton().apply { $0.setImage(UIImage(named: "UserLocation"), for: .normal) $0.addTarget(self, action: #selector(focusUserLocation), for: .touchUpInside) $0.transla

是否有任何方法可以在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)->Void
的闭包,运行它并将
self
传递给它,然后简单地返回
self

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

尝试按如下方式扩展
NSObject

extension NSObject {   
    func apply<T>(_ block: (T)->Void) -> T
    {
        block(self as! T)
        return self as! T
    }
}
这并不方便,也使得整个想法不值得努力。该类型已在对象创建时指定,应该可以不显式重复该类型


谢谢

我遇到了同样的问题,最后与一名操作员一起解决了这个问题:

infix operator <-< : AssignmentPrecedence
func <-<<T:AnyObject>(left:T, right:(T)->()) -> T
{
  right(left)
  return left
}

let myObject = UIButton() <-< { $0.isHidden = false }
中缀运算符HasApply协议
首先,让我们定义
HasApply
协议

protocol HasApply { }
和相关扩展

extension HasApply {
    func apply(closure:(Self) -> ()) -> Self {
        closure(self)
        return self
    }
}
接下来让我们使
NSObject
符合
haspapply

extension NSObject: HasApply { }
就这样 让我们测试一下

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

print(button.titleLabel?.text) // Optional("Tap me")
考虑 我不会使用
NSObject
(这是Objective-C做事方式的一部分,我认为在将来的某个时候它会被删除)。我更喜欢像
UIView
这样的东西

有一个叫做
Then
的可用程序正好可以实现这一点。只是它使用
然后
而不是
应用
。只需导入
,然后导入
,然后您就可以按照OP的要求执行以下操作:

import Then

myObject.then {
    $0.objectMethod()
}

let label = UILabel().then {
    $0.color = ...
}
协议是如何实现的:


如果你对自定义操作符不过敏,Alain有一个很好的答案。如果你不想使用这些,我能想到的最佳选择是:

@discardableResult func apply<T>(_ it:T, f:(T)->()) -> T {
    f(it)
    return it
}
这并不完全相同,但总体来说效果相当好,并且有一个优点,即T完全不受限制。这显然是一个人为的例子,但是:

func apply<T,R>(_ it:T, f:(T)->R) -> R {
    return f(it)
}

我自己仍然对Swift中的泛型感到满意。但是,对于任何
NSObject
,您都无法执行您试图执行的操作。在UIControl中定义了
addTarget(:for:)
方法,并且
setImage(:for:)
特定于
UIButton
。您是对的,这正是我希望将具体类型(可能作为泛型类型参数)放入apply()函数声明的原因。那么静态类型检查将不允许我调用错误的方法。如果对你来说足够好的话,我可以发布一个answer@AlexJenter如果您有一个
UIButton()
,并希望使用apply对其进行配置,则不需要任何样式。只要调用
按钮。装饰器。应用
@iWheelBuy:我明白了。谢谢。哇,真不错,谢谢!这样做的另一个好处是,它不要求类型是NSObject或UIView的后代。这是天才。它起作用了。谢谢我会接受这个答案,因为它最直接地回答了问题。然而,Alain T.和iWheelBuy的asnwers也很棒。闭包的简单使用很好。(投票)我想得太多了。好吧,每个漂亮的图书馆!还添加了方便的“with”和“do”方法。感谢您,这可能值得一提:这并没有真正绕过扩展
任何
的限制。他们只是手动扩展一大堆不同的类型,以符合
然后
extension Then where Self: Any {
    public func then(_ block: (Self) throws -> Void) rethrows -> Self {
        try block(self)
        return self
    }
@discardableResult func apply<T>(_ it:T, f:(T)->()) -> T {
    f(it)
    return it
}
let button = apply(UIButton()) { $0.setTitleText("Button") }
func apply<T,R>(_ it:T, f:(T)->R) -> R {
    return f(it)
}
print("\(apply(32) { $0 + 4 })")