swift - UILabel text not renderer when using rende

2019-08-06 02:33发布

问题:

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)
        }
    }
}

回答1:

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: of NSString to draw your text.



回答2:

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.

dispatch_async(dispatch_get_main_queue()) {
    completion(image)
}