When responding to NSNotifications, what is the best practice for updating UIViews

别来无恙 提交于 2019-12-08 00:44:30

问题


Since the NSNotification invokes its selector on a thread other than the main thread, I notice that any changes that you make to UIViews or other interface elements in response to that notification are often slow to take effect. This is most acute if the main thread is busy (as mine often is!).

I can solve the problem by calling "performSelectorOnMainThread:". Is this really the best practice?

- (void) gotMovieSaveFinishNotication: (NSNotification *) not {
NSURL *exportMovieURL = (NSURL *) [not object];
//saving the composed video to the photos album
ALAssetsLibrary* library = [[[ALAssetsLibrary alloc] init] autorelease];

if(![library videoAtPathIsCompatibleWithSavedPhotosAlbum: exportMovieURL]) {
    NSLog(@"videoAtPathIsCompatibleWithSavedPhotosAlbum fails for: @",exportMovieURL);
    return;
}

[library writeVideoAtPathToSavedPhotosAlbum:exportMovieURL 
                            completionBlock:^(NSURL *assetURL, NSError *error)
 {
     [self performSelectorOnMainThread:@selector(setTintToNormal)
                            withObject: NULL
                         waitUntilDone: YES];

     if(error)
     {
         DLog(@"The video saving failed with the following error =============== %@",error);//notify of completion
     }
     else
     {
         DLog(@"The video is saved to the Photos Album successfully");

     }


 }];

}


回答1:


NSNotificationCenter sends the notification on the same thread that you call postNotification on! So it could be the main thread, or a background thread.

Btw, You shouldn't be making changes to the UI from non-main threads, full stop -- it's not even a matter of slowness, you just shouldn't be doing it, things can fall over, etc.

Your solution certainly is workable, but there's a slightly different (and possibly better) way. See this page for info:

http://www.cocoanetics.com/2010/05/nsnotifications-and-background-threads/

To summarise, the approach at the above link deals with the problem by actually calling the method to generate a notification on the main thread, via some handy helper methods in a category. Could be useful! Feels a bit 'neater' than your solution of calling performSelectorOnMainThread from the actual notification receipt method, because with your current technique you could end up with lots of performSelectorOnMainThread calls whereever you receive a notification in your app.

Also, this is useful info:

http://cocoadev.com/index.pl?NotificationsAcrossThreads




回答2:


Yes. All UI related methods should only be called on the main thread.

The other option you have is to use GCD and send it to main queue:

dispatch_async(dispatch_get_main_queue(), ^{
    // do some stuff on the main thread here...

    [self setTintToNormal];
});

also, consider waitUntilDone:NO. Whenever possible, don't block.



来源:https://stackoverflow.com/questions/5292004/when-responding-to-nsnotifications-what-is-the-best-practice-for-updating-uivie

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!