2

由于 NSNotification 在主线程之外的线程上调用它的选择器,我注意到您对 UIView 或其他界面元素所做的任何更改以响应该通知通常会缓慢生效。如果主线程很忙(我的经常是这样!),这是最严重的。

我可以通过调用“performSelectorOnMainThread:”来解决这个问题。这真的是最佳实践吗?

- (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");

     }


 }];

}

4

2 回答 2

3

NSNotificationCenter 在您调用的同一线程上发送通知postNotification!所以它可能是主线程,也可能是后台线程。

顺便说一句,你不应该从非主线程对 UI 进行更改,句号——这甚至不是慢的问题,你不应该这样做,事情可能会崩溃,等等。

您的解决方案当然是可行的,但有一种稍微不同(可能更好)的方法。有关信息,请参阅此页面:

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

总而言之,上述链接中的方法通过类别中的一些方便的辅助方法实际调用该方法以在主线程上生成通知来处理该问题。可能有用!感觉比您performSelectorOnMainThread从实际通知接收方法调用的解决方案更“整洁”,因为使用您当前的技术,无论performSelectorOnMainThread您在应用程序中收到通知的任何位置,您都可能会收到大量调用。

此外,这是有用的信息:

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

于 2011-03-13T20:34:26.953 回答
2

是的。所有与 UI 相关的方法都应该只在主线程上调用。

您拥有的另一个选择是使用 GCD 并将其发送到主队列:

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

    [self setTintToNormal];
});

另外,考虑 waitUntilDone:NO。只要有可能,不要阻止。

于 2011-03-13T20:28:36.260 回答