Is there any way to get the following working in Swift 3?
let button = UIButton().apply {
$0.setImage(UIImage(named: \"UserLocation\"), for: .normal
First of all lets define the HasApply
protocol
protocol HasApply { }
and related extension
extension HasApply {
func apply(closure:(Self) -> ()) -> Self {
closure(self)
return self
}
}
Next let make NSObject
conform to HasApply
.
extension NSObject: HasApply { }
Let's test it
let button = UIButton().apply {
$0.titleLabel?.text = "Tap me"
}
print(button.titleLabel?.text) // Optional("Tap me")
I wouldn't use
NSObject
(it's part of the Objective-C way of doing things and I assume it will be removed at some point in the future). I would prefer something likeUIView
instead.
extension UIView: HasApply { }
Alain has a good answer if you're not allergic to custom operators. If you'd rather not use those, the best alternative I could come up with was:
@discardableResult func apply<T>(_ it:T, f:(T)->()) -> T {
f(it)
return it
}
which then allows you to use:
let button = apply(UIButton()) { $0.setTitleText("Button") }
It's not quite the same, but works out pretty well in general and has the advantage that T is completely unrestrained. It's an obviously contrived example, but:
func apply<T,R>(_ it:T, f:(T)->R) -> R {
return f(it)
}
even allows:
print("\(apply(32) { $0 + 4 })")
There's a very good and simple Cocoapods library available called Then
that does exactly that. Only that it uses then
instead of apply
. Simply import Then
and then you can do as the OP asked for:
import Then
myObject.then {
$0.objectMethod()
}
let label = UILabel().then {
$0.color = ...
}
Here's how the protocol is implemented: https://github.com/devxoul/Then/blob/master/Sources/Then/Then.swift
extension Then where Self: Any {
public func then(_ block: (Self) throws -> Void) rethrows -> Self {
try block(self)
return self
}
I had the same issue and ended up solving it with an operator:
infix operator <-< : AssignmentPrecedence
func <-<<T:AnyObject>(left:T, right:(T)->()) -> T
{
right(left)
return left
}
let myObject = UIButton() <-< { $0.isHidden = false }