开发者

dispatch_async has lag somewhere, can't find where. is there an NSLog problem?

So i have this code:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

//Bunch of code

NSLog(@"Test");

});

which runs and returns nslog immediately. But the results of the code only appear on the screen a few seconds delay. Is there a problem with nslog being used here, which means it's called before it would usually, making it seem speedy when really it isn't. I'm confused as to where this delay is coming from, as the NSLog is right at the end of all the code which runs then.

Also, another solution to my problem, is it possible to get an NSLog when every method is called (a bit like NSZombiesEnabled i suppose) 开发者_Go百科so i can make sure there isn't some bit which i didn't notice taking up the sweet response time of my app?


UIKit isn’t thread-safe. Any calls you make that affect your UI need to be made on the main thread, or you’ll get weird, unpredictable behavior. Example:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Background code that doesn't need to update the UI here

    dispatch_async(dispatch_get_main_queue(), ^{
        // UI code here
    });
});


Recently I had a similar problem myself. Most likely your delayed updates are stuff you are doing on the user interface. And here's the problem: you are not running in the main thread of the application (also called the UI thread). Therefore, whatever you change to the user interface won't actually be visible until... it feels like showing up, which tends to happen with a redraw triggered by something else in the application.

What you have to do is inside your block queue your graphical updates in the UI thread like this:

dispatch_async(dispatch_get_main_queue(), ^{
        // Do GUI stuff.
    });

Sometimes your block might be big or just using code which was previously run on the main thread, so it is difficult to move all of it to a specific place to run it on the main queue. For these situations, queue a forced refresh in the UI thread at the end of your block:

dispatch_async(dispatch_get_main_queue(), ^{
        [self.somewidget setNeedsDisplay];
        [self.view setNeedsDisplay];
        [self.dontforgetme setNeedsDisplay];
    });

With regards to your "app taking up the sweet response time of my app", it seems that you are trying to use GDC to avoid blocking the user interface. To make sure programatically that you don't happen to do CPU intensive operations in the UI thread, and vice versa, you run GUI updates in the UI block, I've made myself the following macros:

/// Stick this in code you want to assert if run on the main UI thread.
#define DONT_BLOCK_UI() \
    NSAssert(![NSThread isMainThread], @"Don't block the UI thread please!")

/// Stick this in code you want to assert if run on a background thread.
#define BLOCK_UI() \
    NSAssert([NSThread isMainThread], @"You aren't running in the UI thread!")

As you can see by the comments, I tend to use these macros at the beginning of methods I want to make sure I'm not using by error in the wrong place. I've put these macros and more random stuff at https://github.com/gradha/ELHASO-iOS-snippets which you may find useful.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜