7

I know it's safe to draw on any thread so long as I call

UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
UIGraphicsEndImageContext();

on the same thread.

Taking a screenshot of a view via this method takes about 300 ms, which is not bad, but I'm in a tight situation, so I want to do it in a background thread.

Here's what I'm doing:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
        [view.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    });

The only thing here in question is the view, which lies on the main thread. Is it safe to call renderInContext on a view.layer from a background thread? Or generally, is it safe to read-only of a UIKit object from another thread?

(And please don't give me the default "UIKit is not thread safe" answer. I already know that. This here is a special case (and don't tell me there are no special cases).)

(the code above works fine, but I'm not sure if that's just a coincidence.)

Snowman
  • 31,411
  • 46
  • 180
  • 303
  • I don't think you will get a definitive answer to this question because nowhere in the documentation Apple will state anything other than `UIKit is is not thread safe` (along with the listed exceptions). What you will get are opinions and experiences from other people but as you said, the code above works fine but who's to say that it always will and even if someone else tells you that it will, will it? – Rog Jul 06 '12 at 04:29
  • Do threading rules apply to modifying or reading an object as well? – Snowman Jul 06 '12 at 04:31
  • And what if I make a copy of the view before, so that I'm sure I'm this method would be the only one that has access to this new copy? – Snowman Jul 06 '12 at 04:32

1 Answers1

7

Core Graphics and Core Animation being low-level APIs, are generally thread safe. However, the same rules about access still apply: Any work must not be accessed by more than one thread at the same time, else drawing will fail and your app will crash. I would be wary (but not afraid) of UIImage, as UIKit objects aren't just not thread safe, they're basically ticking time bombs in background threads, and will happily dive straight off a cliff into Exception Land for no good reason. However, because UIImage is just a CGImage wrapper, again, most drawing is thread safe.

CodaFi
  • 43,043
  • 8
  • 107
  • 153
  • So is there a clever alternative for taking a screenshot in the background? How about using NSData in the bg thread, and using that to build an image on the main thread? – Snowman Jul 06 '12 at 04:36
  • Screenshots in the background? Not possible without IOSurface, which Apple is now quite vividly aware of thanks to Display Recorder, however, if that doesn't matter, see [here](http://stackoverflow.com/questions/11090184/how-does-the-ios-app-display-recorder-record-the-screen-without-using-private-ap/). – CodaFi Jul 06 '12 at 04:37
  • 3
    Yes, it's entirely possible, as you have seen yourself, and is safe. God, I wish apple would just bite the bullet and make UIKit thread safe so we wouldn't have to have these discussions in the first place... Aw well, maybe in iOS 7, eh? – CodaFi Jul 06 '12 at 04:45
  • Why does the fact that they're low-level APIs make them more likely to be thread-safe? – Peter Schorn Aug 11 '22 at 09:50