0

I have this function:

extension UIImage {

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

}

How can I change it into like this?

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
    }

}

I want that the result of UIGraphicsGetImageFromCurrentImageContext() becomes the initiated "self". But the result is already a UIImage. I don't suppose I should use "mutating" in this function?

Chen Li Yong
  • 5,459
  • 8
  • 58
  • 124
  • 3
    What was wrong with what you had to start with? A static factory method is _exactly_ the way to do this. – matt Feb 09 '18 at 03:17
  • 1
    I think you can't; see this answer: https://stackoverflow.com/a/37612406/433373 – Nicolas Miari Feb 09 '18 at 03:18
  • @matt I do not want to create a factory method. I want to create an initializer, which works slightly looks like a "type cast" sort of matter. I do not _produce_ an image. My intent is to _convert_ a type of image from one type to another, which is why the form of factory is not exactly communicating my intent. – Chen Li Yong Feb 09 '18 at 03:43
  • @NicolasMiari yeah I kinda guess that, but I just curious whether if we have some workaround with this limitation. – Chen Li Yong Feb 09 '18 at 03:48

1 Answers1

4

As the error states UIImage is immutable. What you can do is to get a CGImage from your outputImage and use UIImage init(cgImage: CGImage) initializer to initialize a new image from it:

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)
    }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571