I need to generate an image from a custom view composed by an UIImageView
and an UILabel
.
I can't use the new iOS 7 drawViewHierarchyInRect:afterScreenUpdates:
because I have some ugly glitch on iPhone 6/6+ (iOS8 scale glitch when calling drawViewHierarchyInRect afterScreenUpdates:YES)
So I did it the old fashion way using renderInContext:
which works well but it's quite slow. I'm using image generation to display markers in a GMSMapView
(god I missed MapKit
...) but the user experience is quite bad because of lags due to those image generation.
So I try to perform the image creation operation in a background thread in order to have something smooth but here's the problem : the majority of my labels are not rendered.
Anyone as already faced this issue ?
Here's the code I used :
func CGContextCreate(size: CGSize) -> CGContext {
let scale = UIScreen.mainScreen().scale
let space: CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()
let bitmapInfo: CGBitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.rawValue)
let context: CGContext = CGBitmapContextCreate(nil, Int(size.width * scale), Int(size.height * scale), 8, Int(size.width * scale * 4), space, bitmapInfo)
CGContextScaleCTM(context, scale, scale)
CGContextTranslateCTM(context, 0, size.height)
CGContextScaleCTM(context, 1, -1)
return context
}
func UIGraphicsGetImageFromContext(context: CGContext) -> UIImage? {
let cgImage: CGImage = CGBitmapContextCreateImage(context)
let image = UIImage(CGImage: cgImage, scale: UIScreen.mainScreen().scale, orientation: UIImageOrientation.Up)
return image
}
extension UIView {
func snapshot() -> UIImage {
let context = CGContextCreate(self.frame.size)
self.layer.renderInContext(context)
let image = UIGraphicsGetImageFromContext(context)
return image!
}
func snapshot(#completion: UIImage? -> Void) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let image = self.snapshot()
completion(image)
}
}
}
I think the problem is that the completion is executed in this background queue. UI updates have to be on the main thread so might work with.
It seems there are issues to rendering
UILabel
in an other thread than the main one.Your best option is to use the method
drawInRect:withAttributes:
ofNSString
to draw your text.