Peter Warbo
Peter Warbo

Reputation: 11710

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 (viewDidAppear:) 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.

Upvotes: 1

Views: 3432

Answers (4)

Deepak Danduprolu
Deepak Danduprolu

Reputation: 44633

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];
   });
});

Upvotes: 1

    -(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];


    }

Upvotes: 0

marcus
marcus

Reputation: 2531

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:

Upvotes: 1

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?

Upvotes: 0

Related Questions