Ios 如何在Swift中编写泛型apply()函数?
是否有任何方法可以在Swift 3中实现以下功能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
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 })")