9

So, as mentioned in this answer and in the iOS 4.0 release notes, UIKit now has some thread-safe drawing facilities:

Drawing to a graphics context in UIKit is now thread-safe. Specifically:

  • The routines used to access and manipulate the graphics context can now correctly handle contexts residing on different threads.
  • String and image drawing is now thread-safe.
  • Using color and font objects in multiple threads is now safe to do.

That's great, but how do you use it?

As far as I'm aware, any time you're not inside -drawRect: you can only draw using the UIKit/UIGraphics stuff if you've created your own context through UIGraphicsBeginImageContext() or UIGraphicsPushContext(), but those functions are not thread safe according to the docs, and -drawRect() is always called on the main thread.

I assume that creating an image context on the main thread and then starting the background method would be a really bad idea, due to race conditions aplenty.

So, how do I use this multithreaded UIKit-based drawing stuff that was introduced in iOS 4? What other ways of getting an active UIKit graphics context have I missed?

P.S. I know that I could just draw using Core Graphics and be done with it. For various reasons (legacy code) I'd like to continue using the UIKit based drawing methods.

Community
  • 1
  • 1
Amy Worrall
  • 16,250
  • 3
  • 42
  • 65

1 Answers1

8

My belief, based on some experience trying it and based on various documents, is that the docs for UIGraphicsPushContext() are incorrect.

I believe UIGraphicsPushContext() is in fact thread safe. The particular indication that this is true is QA1637, which says "Beginning with iOS 4.0, drawing to a graphics context in UIKit is thread-safe. This includes accessing and manipulating the current graphics stack, drawing images and strings, and usage of color and font objects from secondary threads." (emphasis mine)

I acknowledge that it is always a dicey proposition to assume thread safety in contradiction to the docs. But I believe this is a documentation error. I have opened rdar://11161530 to track it. Please dupe.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • I've actually just opened a DTS issue about this, so I'll hopefully find out from there. The thing I didn't mention in the question was that in my trials (although I was using ...beginImageContext), most of the time things were working fine, but sometimes I was getting a crash in `NSString drawInRect:withFont:`. It's annoyingly not easily reproducible, but whenever it crashes it's there. I'm trying to work out if I'm doing something wrong or if this will just never work. – Amy Worrall Mar 31 '12 at 15:06
  • I hadn't seen that kind of crash before, but I haven't been overly aggressive in my experiments. This is quite disturbing and may suggest that my belief is incorrect. Please let us know what the DTS result is. – Rob Napier Mar 31 '12 at 15:17
  • More info: the specific thing that crashes is `WebCore::FontFallbackList::~FontFallbackList() ()`. – Amy Worrall Mar 31 '12 at 15:27
  • 1
    Ah... remember that UIWebView is definitely, absolutely, not thread safe. I wouldn't try to do *anything* with a webview off the main thread. Some more discussion about it: http://stackoverflow.com/questions/4660999/create-a-uiimage-by-rendering-uiwebview-on-a-background-thread-iphone – Rob Napier Mar 31 '12 at 15:33
  • No, I'm not using a web view anywhere. It's called from the NSString drawing code, call stack here: http://pastebin.com/jr4C3n3b – Amy Worrall Mar 31 '12 at 15:39
  • Interesting; they seem to be calling out to WebStringDrawing, which then calls into WebKit, which generally is not thread safe. This could be considered bug given their statement that UIKit drawing is thread safe. I'd make sure your stack trace is in the DTS; I'm very interested in what they say. – Rob Napier Mar 31 '12 at 16:56
  • 2
    I'm definitely starting to think it's a bug in the frameworks. Not 100% yet but we believe the crash only happens when font substitution is required: some of our text had hairline space characters which aren't found in the font we wanted to use. Removing the offending characters seems to be working. I'll report this to DTS when they get back to me. – Amy Worrall Apr 02 '12 at 10:29
  • Did you hear back from DTS? We're having the exact same issue. Calling NSString drawInRect from a background thread is causing occasional crashes when it ends up doing the drawing via WebKit. – A. Z. Jun 04 '12 at 18:00
  • @ameir My analysis is that it's thread-safe in 4.x and broken in 5.x: http://stackoverflow.com/questions/11589768/ – tc. Jul 25 '12 at 20:33