Обработка ошибок инициализации класса в расширении Swift

Я переписываю категорию Objective C ниже в Swift:

@implementation UIImage (Extra)

+ (UIImage *)validImageNamed:(NSString *)name
{
    UIImage *image = [self imageNamed:name];
    NSAssert(image, @"Unable to find image named '%@'", name);
    return image;
}

Это требует реализации в качестве удобства инициализации, но как я могу проверить, если назначенный инициализатор self.init(named:) успешно?

extension UIImage {
    convenience init(validateAndLoad name: String!) {
        self.init(named: name)

        // need to assert here if self.init fails
    }

Когда происходит сбой вызова self.init(named:), инициализация расширения прекращается.

Я попытался создать экземпляр UIImage и присвоить его себе, но это не компилируется.

Конечно, вспомогательный метод может использоваться как в версии ObjC:

extension UIImage {

    class func validImage(named name: String) -> UIImage {
        var image = UIImage(named: name)
        assert(image == nil, "Image doesn't exist")
        return image
    }

Но есть ли способ реализовать это с помощью инициализатора?

3 ответа

Решение

Теперь вы можете создавать неудачные инициализаторы в расширениях; однако инициализаторы не могут быть определены в протоколе.

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

В отличие от Objective-C, инициализаторы Swift не возвращают себя, поэтому проверка на ошибки инициализации невозможна. Инженер Apple предложил вместо этого использовать фабричный метод с необязательным типом возврата:

class ImageFactory {

    class func validImage(named name: String) -> UIImage? 
    {
        var image = UIImage(named:name)
        assert(image != nil, "fail")
        return image;
    }
}

Инженер Apple указал, что они работают над тем, чтобы встроить что-то в язык, который обойдется с помощью методов класса фабрики.

Я бы написал метод, как показано ниже:

extension UIImage {

class func validImage(named name: String) -> UIImage? {
    var image = UIImage(named: name)
    return image
}

В Swift вы можете использовать дополнительные. Если здесь нет изображения с заданным именем, метод вернет ноль.

Другие вопросы по тегам