Having UIView drawRect occur in a background thread
Asked Answered
S

2

6

I would like to have a UIView subclass that implements a method similar to setNeedsDisplay, except that redrawing (i.e., that would usually be called via drawRect:) will occur in a background thread sometime soonish, rather than at the end of the current update cycle.

It might be called setNeedsAsynchronousDisplay. Or the existing setNeedsDisplay could get hijacked and not cause redraw at the end of the cycle, or whatever, as long as it lets the redraw not happen on the main thread blocking screen updating an interaction until its completed.

Until the redraw occurs, the view can continue to use its current drawn representation.

Is something along these lines reasonably doable?

Thanks!

Specious answered 15/1, 2014 at 13:54 Comment(0)
K
12

Yes it is possible. You will probably need to generate the content view as an image in the background and push the images into a nsdictionary or array.

So while your background is generating the images you can just show the image in drawrect function by rendering the image, providing the image has been generated.

A WWDC video that shows how to do it: WWDC 2012 session 211 - Building Concurrent User Interfaces on IOS. Here is the video description:

For a great user experience, it's essential to keep your application responsive while it renders complex UI elements and processes data. Learn how to use concurrency at the UIKit layer to perform drawing and other common operations without blocking user interaction.

Krueger answered 15/1, 2014 at 14:6 Comment(5)
After watching the video, I was very excited and even tried to build one myself. It is more practical for cell views that don't have many interactions like buttons or highlight state. Let me know if you have built it one yourself.Krueger
Thanks @Ethan, that certainly sounds helpful from the description. I'll take a look at that today.Specious
Oh, I implemented this and it works really nicely. Thanks :-)Specious
really great work by Apple Team there , thnx for video @Ethan FangStipple
Unfortunately this video is no longer available anywhere. Did anyone have a chance to save a copy or write up notes from it before Apple pulled it down?Dimond
A
-3

No. View Drawing must occur in the foreground. Apple makes that very clear in their docs.

EDIT: You're right that you CAN do Core Graphics drawing in the background as long as it's not in a UIView object's drawing methods. You'd have to do the drawing in the background, then send a message to the main thread to update your view object once drawing is complete.

I would suggest not trying to override setNeedsDisplay. Instead, add your new setNeedsAsynchronousDisplay method. In that method, queue rendering code to an async queue using GCD calls. Once the rendering is complete, have the rendering code send a setNeedsDisplay message to self on the main thread.

Then in your subclass's drawRect method, check for pre rendered images and draw those into the view's context instead of the normal code.

A downside of this is that merely by implementing drawRect, you may slow down rendering because the system calls that instead of doing other, more efficient things to render your view's content.

Angelicangelica answered 15/1, 2014 at 14:0 Comment(2)
Thank you @Duncan C, but I don't believe this is the case as of iOS 4 for Core Graphics operations (but not their UI wrappers). Please see this technical note at Apple. I suspect that UIView updates do need to be in the main thread, but this doesn't mean that the drawing can't happen in the background on another surface and then be swapped in. I'm after ideas / suggestions / best practice / complete solutions for this.Specious
I have never used "drawRect inContext", maybe worth a try.Krueger

© 2022 - 2024 — McMap. All rights reserved.