开发者

When to load data in UITableViewController?

I am currently loading data coming from a JSON service in the viewDidLoad method in UITableViewController. The problem is that is the data takes time to be retrieved and parsed, the view takes time to be created. Wher开发者_运维知识库e is the best place to load this data? I assume that there is a hook somewhere to load data after the view is created. By doing this I will be able to use some UIActivityIndicatorView in the final view. Thanks


Finally here is a solution based on comments: Launch a thread in viewDidLoad to get data without blocking all:

- (void) viewDidLoad
{
    dataLoaded = NO;

    [self initSpinner];
    [self launchLoadData];
...
}

-(void)launchLoadData {
    NSLog(@"Launching thread");
    [NSThread detachNewThreadSelector:@selector(loadData) toTarget:self withObject:nil];
}

- (void) loadData {
    dataLoaded = NO;
    NSLog(@" thread launched");
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [self loadDataFromURL:nil];
    dataLoaded = YES;
    [self.tableView reloadData];
    [pool release];
}

- (void)loadDataFromURL:(NSString*)url {
    // start the spinner to show that loading may be time consuming...
    [NSThread detachNewThreadSelector: @selector(spinBegin) toTarget:self withObject:nil];
    JSONLoader *loader = [[JSONLoader alloc] init];
    self.accounts = [loader getAccountsFromURL:@"http://foo/bar/repository.json"];
    [loader release];
    //[NSThread sleepForTimeInterval:3];
    [NSThread detachNewThreadSelector: @selector(spinEnd) toTarget:self withObject:nil];
}

and use the flag to display or not data in table. tableView reloadData will do the rest when called from thread.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (dataLoaded) return [self.accounts count];
    return 0;
}


I think what you're trying to ask is the workflow for displaying data from a web service in a UITableView.

Here's what I recommend:

  • Your viewDidLoad makes a NSURLRequest for your JSON file. Also adds a loading view to the current view (I use a UIView with a black bg (0.5 alpha), plus a label and UIActivityIndicator). In this method you also set a BOOL ivar (which you need to add in your header) called loaded to NO.

  • You concat your NSURLRequest data as it comes down into a mutable data object.

  • When your NSURLRequest finishes, you turn it's data into a string, and parse the JSON into an array of some sort (or dictionary if you want). In the same method you remove the loading view, and change your boolean loaded to YES. You then tell the tableView to reload it's data: [self.tableView reloadData];

Here's where the magic happens... in your table view methods

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (loaded) return [myArrayOfJSONObjects count];
    return 0; // Will only return 0 if the data is not downloaded
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger row = [indexPath row];

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell...
    if (loaded) {
        cell.textLabel.text = [myArrayOfParsedJSONObjects objectAtIndex:row];
        //Anything else you want to set
    }
    else {
        //Do nothing :) - you shouldn't reach this else anyway because your numberOfRows method should stop it
    }
}


You can open new view and show UIActivityIndicator with message for user, what you loading fresh data for him.

As for me, this is best choice, because interface remains responsible and user see what you actually do something and app not hanged.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜