Как я могу сделать так, чтобы объект того же класса стал возвращаемым значением инициализатора?

У меня есть эта функция:

extension UIImage {

    static func from(layer: CALayer) -> UIImage? {
        UIGraphicsBeginImageContext(layer.frame.size)
        layer.render(in: UIGraphicsGetCurrentContext()!)
        let outputImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return outputImage
    }

}

Как я могу изменить это на такое?

extension UIImage {

    convenience init(layer: CALayer) {
        self.init();
        UIGraphicsBeginImageContext(layer.frame.size)
        layer.render(in: UIGraphicsGetCurrentContext()!)
        let outputImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self = outputImage; // Error: cannot assign to self: self is immutable
    }

}

Я хочу, чтобы результатом UIGraphicsGetImageFromCurrentImageContext() стало инициированное «я». Но результат уже UIImage. Я не думаю, что мне следует использовать «мутацию» в этой функции?


person Chen Li Yong    schedule 09.02.2018    source источник
comment
Что было не так с тем, с чего вы должны были начать? Статический фабричный метод точно подходит для этого.   -  person matt    schedule 09.02.2018
comment
Я думаю, вы не можете; см. этот ответ: stackoverflow.com/a/37612406/433373   -  person Nicolas Miari    schedule 09.02.2018
comment
@matt Я не хочу создавать фабричный метод. Я хочу создать инициализатор, который работает немного похоже на тип приведения. Я не создаю изображение. Мое намерение состоит в том, чтобы преобразовать тип изображения из одного типа в другой, поэтому форма factory не совсем соответствует моим намерениям.   -  person Chen Li Yong    schedule 09.02.2018
comment
@NicolasMiari да, я догадываюсь об этом, но мне просто любопытно, есть ли у нас обходной путь с этим ограничением.   -  person Chen Li Yong    schedule 09.02.2018


Ответы (1)


Поскольку ошибка указывает, что UIImage неизменяем. Что вы можете сделать, так это получить CGImage из вашего outputImage и использовать UIImage init(cgImage: CGImage) initializer для инициализации нового образа из него:

extension UIImage {
    convenience init?(layer: CALayer) {
        UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, 0)
        defer { UIGraphicsEndImageContext() }
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        layer.render(in: context)
        guard let outputImage = UIGraphicsGetImageFromCurrentImageContext()?.cgImage else {
            return nil
        }
        self.init(cgImage: outputImage)
    }
}
person Leo Dabus    schedule 09.02.2018
comment
О, я никогда не думал об использовании инициализатора cgImage. Спасибо! - person Chen Li Yong; 09.02.2018
comment
Действительно очень умно! :-) - person Nicolas Miari; 09.02.2018