How to write a generic apply() function in Swift?
The HasApply protocol
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 { }
That's it
Let's test it
let button = UIButton().apply {
$0.titleLabel?.text = "Tap me"
}
print(button.titleLabel?.text) // Optional("Tap me")
Considerations
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 { }
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 }