Debugging threads and UI Update crashes – Yes, its happening to you

Threads and the OS X UI

So, its common knowledge that using threads allows your app to do processing in the background. On OS X it is also critical you don’t block the thread, or you’ll slow down the OS and treat your users to the magical beachball..

 

Busy

In order to do this, on most of my OS X Apps, I put just about everything into queues that run on alternate threads. The idea is that you do the processing int he background, and only update the UI when needed/rarely:

 

primaryTask=dispatch_queue_create("com.you.app.task1",NULL);
dispatch_async(primaryTask,^{
            [self doStuffOnTheBackgroundThread];
        });

 

The issue is that on the other background thread you will want to update the UI, or ask for input etc…. You can’t just go crazy and update things directly, or some very random amount of the time it’ll crash on your users, causing them to descend on you in a hail of one-star reviews:

[drive1Button setImage:picturel];

You must rather dispatch that operation to the main thread or perform the selector on main thread or whatever:

if(![NSThread isMainThread]){
        dispatch_async(dispatch_get_main_queue(),
                       ^{
                           [drive1Button setImage:picturel];
                           
                       });
    }
    else
   {
                  // WTF? This shouldn't be running on this thread!
    }

Getting to the point.

All good… but what if you’re getting all thread-ninja like I am with multiple threads each independently copying files, while another polls for changes and yet another does something else… its very easy to call a UI update from some background thread… and so you need a way of “break on UI update from non-main thread”

No problem! Click the breakpoint list icon (no clue if thats the real name) – the little points-to-the-right arrow looking deal:

Screen Shot 2016-02-25 at 3.52.03 PM

And now click the + sign at the bottom left of the Xcode window to add a new breakpoint:

Screen Shot 2016-02-25 at 3.53.15 PM

Add a symbolic breakpoint, and have it trip on setNeedsDisplay: which is called if anything updates anything… and add a pinch of logic to make this only trip if not on the main thread. (Note that the condition needs to be a BOOL, so you have to cast it)

Screen Shot 2016-02-25 at 3.57.38 PM

And then boom, there you have it… almost…

Make sure you have no spinning animated progress items – apparently its totally cool for Apple to call that badboy from some other thread… so just comment out all startAnimating on progress bars:  // [workingSpinner startAnimation:self];

I highly suggest running  this every time you are going to release… it catches a lot of “I don’t know why my app just mysteriously crashes”

Enjoy

J

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s