I'm rewriting an Objective C category below to Swift:
@implementation UIImage (Extra)
+ (UIImage *)validImageNamed:(NSString *)name
{
UIImage *image = [self imageNamed:name];
NSAssert(image, @"Unable to find image named '%@'", name);
return image;
}
This asks to be implemented as an convenience init, but how can I check if designated initializer self.init(named:) succeeds?
extension UIImage {
convenience init(validateAndLoad name: String!) {
self.init(named: name)
// need to assert here if self.init fails
}
When self.init(named:) call fails, extension's init stops executing.
I've tried creating an UIImage instance and assigning it to self, but this doesn't compile.
Of course, a helper method can be used like in ObjC version:
extension UIImage {
class func validImage(named name: String) -> UIImage {
var image = UIImage(named: name)
assert(image == nil, "Image doesn't exist")
return image
}
But is there a way to implement this using an initializer?
You can now create failable initializers in extensions; however, the initializers can not be defined in a protocol.
class Thing {
var text:String?
}
extension Thing {
convenience init?(text:String) {
self.init()
if text == "" {
return nil
} else {
self.text = text
}
}
}
let that = Thing(text: "Hello")
println(that?.text) //prints Optional("Hello")
let empty = Thing(text: "")
println(empty) //prints nil
Unlike Objective-C, Swift initializers don't return self, so checking for initialization failures is not possible. An Apple engineer suggested using a factory method with an optional return type instead:
class ImageFactory {
class func validImage(named name: String) -> UIImage?
{
var image = UIImage(named:name)
assert(image != nil, "fail")
return image;
}
}
The Apple engineer indicated that they are working on building something into the language that will get around using factory class methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With