NSOperationQueue seems to hang on completion for a few seconds
I have a custom view controller that implements the from UITableViewDataSource
and UITableViewDelegate
protocols. When I load data for my table (in my viewDidLoad
method), I create a NSOperationQueue
and a NSInvocationOperation
and add it to the queue. I throw up an activity indicator, and viewDidLoad
exits.
The method used for the operation ends the activity indicator animation.
I have noticed that when the operation completes, there is a 5-7 second pause before the operation really completes, even though by NSLog it looks like the operation's method returned.
I have tried to use Instruments to figure out where the pause is happening, but I can't tell from it because most of my CPU time is spent in system libraries.
Edit Here's an abbreviated version:
@implementation MyViewController
@synthesize ...
- (void)viewDidLoad {
[super viewDidLoad];
self.opsQueue = [[NSOperationQueue alloc] init];
NSInvocationOperation *aiStartOp = [[[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(showActivityIndicators)
object:nil] autorelease];
[self.opsQueue addOperation:aiStartOp];
NSInvocationOperation *dataOp = [[[[NSInvicationOperation alloc]
initWithTarget:self
selector:@selector(dataUpdate)
object:nil] autorelease];
[dataOp addDependency aiStartOp];
[self.opsQueue addOperation:dataOp];
NSInvicationOperation *aiStopOp = [[[NSInvicationOperation alloc]
initWithTarget:self
selector:@selector(hideActivityIndicators)
object:nil] autorelease];
[aiStopOp addDependency:dataOp];
[self.opsQueue addOperation:aiStopOp];
}
/* other stuff */
@end
Just to be clear, the last operation in the queue is this:
- (void)hideActivityIndicators {
DLog(@"hiding activity indicator");
self.portraitChartProgressView.hidden = YES;
[self.portraitChartProgressIndicator stopAnimating];
self.landscapeProgressView.hidden = NO;
开发者_如何学编程 [self.landscapeProgressIndicator startAnimating];
}
What I see in the log is the output of the above log message, followed by a pause of 5 seconds, and then finally followed by the view with the indicator on it being hidden.
Any ideas?
All UI events, drawing etc. need to be performed on the main thread. You can forward calls to the main thread using something like the following.
- (void)hideActivityIndicators {
if (![NSThread isMainThread])
[self performSelectorOnMainThread:@selector(hideActivityIndicators) withObject:nil waitUntilDone:NO];
DLog(@"hiding activity indicator");
self.portraitChartProgressView.hidden = YES;
[self.portraitChartProgressIndicator stopAnimating];
self.landscapeProgressView.hidden = NO;
[self.landscapeProgressIndicator startAnimating];
}
EDIT"
Now that I look a little more carefully, one thing you probably don't need to do is start and stop the "loading" views by adding to an NSOperationQueue
. Likely the only thing that you need to do in in the queue is the data update, then post notifications and delegation to update your views when the data operation is complete.
The TopSongs sample project demonstrates this very well. The forwarding statement to the main thread is based on code in the AppDelegate.m file in the sample.
精彩评论