Reputation: 79103
I'm working on an abstraction that lets me create an object and assign some properties all in one expression:
extension UIView {
func with(_ callback: (UIView) -> Void) -> UIView {
callback(self)
return self
}
}
Usable like so:
let greenView = UIView().with {
$0.backgroundColor = UIColor.green
}
The problem is that when I subclass UIView
(in this case), the with
method still wants to deal with UIView
objects and not the subclass:
class SettingView: UIView {
let setting = UISwitch()
}
let activeSettingView = SettingView().with { (view: UIView) in
let settingView = view as! SettingView // this downcast is required
settingView.setting.isOn = true
}
Is there any way I can specify the type signature for with
so that it'll automatically work with the type of any subclass, and thus no longer require manual downcasting? i.e. like this:
let activeSettingView = SettingView().with { (view: SettingView) in
settingView.setting.isOn = true
}
I've tried looking into generics and protocol extensions, but I haven't found anything suitable yet.
Upvotes: 0
Views: 97
Reputation: 1056
This depends on Swift version In Swift 5.1 you can refer to Self in any class, so just replace UIView with Self
In Swift < 5.1 the only way is to create a protocol like this
protocol Transformable {}
extension Transformable {
func with(_ callback: (Self) -> Void) -> Self {
callback(self)
return self
}
}
extension UIView: Transformable {}
Then it should work
With this protocol you can extend any class, but will have problems with mutating structs
To be able to use this with classes and structs just replace with
with following
extension Transformable {
func with(_ callback: (inout Self) -> Void) -> Self {
var mutable = self
callback(&mutable)
return mutable
}
}
Upvotes: 1