I'm trying to write a generic class function for Swift classes that would allow me to initialize classes using trailing closure syntax.
I have already got it working for specific classes, like for example UILabel.
// Extension for UILabel
extension UILabel {
class func new(_ initialization: (inout UILabel) -> Void) -> UILabel {
var label = UILabel()
initialization(&label)
return label
}
}
// Initialize new UILabel using trailing closure syntax and "new" function
let label = UILabel.new {
$0.textColor = .red
}
However, I want to have this functionality for all subclasses of NSObject, so I'm trying to implement a generic version of the "new" function above. So far I have come up with this:
extension NSObject {
class func new(_ initialization: (inout Self) -> Void) -> Self {
var newSelf = Self()
initialization(&newSelf)
return newSelf
}
}
But this produces the following error: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'NSObject'?
I am trying this in a playground with Swift 5.1 (Xcode 11 beta).
As Hamish said, maybe it's better to leave the init outside so it is more flexible. However there could be a kind of workaround for this using a protocol.
protocol Initializable {
init()
}
extension Initializable {
static func new(_ initialization: (inout Self) -> Void) -> Self {
var newSelf = Self()
initialization(&newSelf)
return newSelf
}
}
extension NSObject: Initializable {}
NSObject
already have an init
so it automatically conforms to Initializable
.
Then write your extension on the protocol.
The only thing to be aware is that you cannot use class
modifier now, as you're in a protocol
.
Not sure if this can lead to problem for the NS_UNAVAILABLE
modifier, I think it could crash at runtime when you use this on a class that is hiding the init.