iOS - viewDidAppear: delayed when showing a UITableView
I'm having a weird problem. I have a Tab Bar application, in it I'm using a Navigation Controller for each of the different tabs and each Navigation Controller has it's own View Controller to display some content.
When I touch a tab I want the tab to be loaded immediately with the view and after it has been loaded (view开发者_Python百科DidAppear:
) I want it to download some data in the viewDidAppear: method.
To test this functionality I have setup the following method. I'm using a NSThread
to simulate doing some lengthy operation that should be done in the background while the view has been loaded. Then I assign the NSArray *test (nonatomic, retain) with some test data and reload the table.
I'm reloading the table because in the viewDidLoad
method I'm setting the table to contain only one empty string (this is because I read that the table is setup before viewDidAppear: is called.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
DLog(@"viewDidAppear running");
[NSThread sleepForTimeInterval:10];
NSArray *array = [[NSArray alloc] initWithObjects:@"Test1", @"Test2", @"Test3", @"Test4", @"Test5", @"Test6", nil];
self.test = array;
[array release];
[table reloadData];
}
So my expected behaviour should be that when touching this particular tab it should load instantly and then after 10 seconds it should be populated with table data from the viewDidAppear: method. But the behaviour is instead that when touching this tab it waits for 10 seconds and then it displays the view with the table data populated.
Calling [NSThread sleepForTimeInterval:10];
will prevent the main thread from doing any updates so you cannot see any user interface changes. If you want to delay reloading of table data as above, check NSObject performSelector:withObject:afterDelay:
NSObject Class Reference
Put the code for reloadData and array setup in a method an call it via performSelector:withObject:afterDelay:
The other answers explain why your main thread is blocked when you use +[NSThread sleepForTimeInterval:]
method.
To handle downloading off the web, you should push your downloading task to a background thread so as to avoid blocking the main thread like you have done here. You can achieve this using Grand Central Dispatch.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
/* Download stuff */
dispatch_async(dispatch_get_main_queue(), ^{
/* Send UI updates back to the main thread. */
[self.tableView reloadData];
});
});
Aren't you putting the wrong thread to sleep? (Namely the one that will create the array)
Seems you wait 10 seconds and then call the table reloadData.
Why are you waiting anyway? Don't you want the tableView to be filled as soon as the data is available?
-(void)executeMe{
NSArray *array = [[NSArray alloc] initWithObjects:@"Test1", @"Test2", @"Test3", @"Test4", @"Test5", @"Test6", nil];
self.test = array;
[array release];
[table reloadData];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
DLog(@"viewDidAppear running");
[self performSelector:@selector(executeMe) withObject:nil afterDelay:10];
}
精彩评论