Reputation: 13033
Is it possible for an instance of a UIView
to call a method which executes a closure, and inside that closure referring to the same instance? This is the non-generic version:
import UIKit
public extension UIView {
func layout(from: (UIView) -> ()) {
from(self)
}
}
When I call it with a UILabel for example, I do not have access to e.g. the text aligment. Is it possible that inside the closure I can refer to the UILabel? I would expect something like this would work:
func layout(from: (Self) -> ()) {
from(self)
}
But it doesn't compile. Is there a workaround? This is what I want:
let label = UILabel(frame: .zero)
label.layout { $0.textAlignment = .natural } // Currenly not working, since $0 = UIView.
Upvotes: 3
Views: 413
Reputation: 188
There are different ways to do it.
Firstly, you could use the closures' variable capturing system in order to directly use the variable inside the closure, without passing it as an argument.
public extension UIView {
func layout(from: () -> ()) {
from()
}
}
label.layout { label.textAlignment = .natural }
Otherwise, if you want to pass a generic UIView
and change the behaviour accordingly to the specific one - since it looks like you know for sure what type you are working on - you can use a downcast:
public extension UIView {
func layout(from: (UIView) -> ()) {
from(self)
}
}
let label = UILabel(frame: .zero)
label.layout { ($0 as! UILabel).textAlignment = .natural }
Anyway, why are you doing:
label.layout { $0.textAlignment = .natural }
instead of:
label.textAlignment = .natural
Is there any particular reason not to do it? I imagine there's something bigger behind the scenes, I'm just curious.
Upvotes: 1
Reputation: 285079
Different approach: Protocol Extension with associated type.
protocol Layout {
associatedtype View : UIView = Self
func layout(from: (View) -> ())
}
extension Layout where Self : UIView {
func layout(from: (Self) -> ()) {
from(self)
}
}
extension UIView : Layout {}
let label = UILabel(frame: .zero)
label.layout { $0.textAlignment = .natural }
Upvotes: 3