开发者

How To Make Scrolling UITableView Smoother?

I have a tableview with about 20 cells with images that are downloaded from the net.

Right now it is choppy when scrolling and it needs to be make more smooth.

My method is:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    CustomCell *cell = (CustomCell*)[tableView dequeueReusableCel开发者_开发技巧lWithIdentifier:CellIdentifier];
    if (cell == nil) {

        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];

        for (id currentObject in topLevelObjects){
            if ([currentObject isKindOfClass:[UITableViewCell class]]){
                cell =  (CustomCell *) currentObject;
                break;
            }
        }
    }

    NSDictionary *article = [entriesArray objectAtIndex:[indexPath row]];
    NSString *title = [article objectForKey:@"title"];
    NSString *date = [article objectForKey:@"publishedDate"];
    NSString *dateEdited = [date substringToIndex:16];

    cell.nameLabel.text  = title;
    cell.dateLabel.text  = dateEdited;

    NSURL *myURL=[NSURL URLWithString:[self.picturesArray objectAtIndex:indexPath.row]]; 
    NSData *myData1 = [[NSData alloc] initWithContentsOfURL:myURL];
    UIImage *myImage = [[UIImage alloc] initWithData:myData1]; 

    cell.imageView.image = myImage;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 2;

    return cell;
}

Any advice?


There's a few issues. Firstly, you have some memory leaks. myData1 and myImage are created but not released.

However, my guess would be that the big performance hits relates to you creating the UIImage. Move this out of this cell request method. Perhaps create a cache of images that you can draw upon. For example, have them as static UIImage objects created in your initialize method.

I think this will solve the bulk of your performance issues. One final tweak would be to remove your for loop from within this method. Perhaps create an NSDictionary so that objects can be looked up directly.


It doesn't appear that you are running the network request on a background thread, which is what you need to be doing. Not only from a performance standpoint but from a stability standpoint as well. What happens if the server you are making the network request to is down? I am not sure on how initWithContentsOfURL: handles failures but your code doesn't seem to be checking for a failure from that method, so it looks like your program will crash as a result of network problems.

Implementing the fetch on a background thread will not cause the main thread to block, allowing your UITableView to scroll much more seamlessly, however the tradeoff for this will be that table view images may be blank for a little while as it waits for the background thread to complete the network request.


This is how you load custom cells

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

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

    NSDictionary *article = [entriesArray objectAtIndex:[indexPath row]];
    NSString *title = [article objectForKey:@"title"];
    NSString *date = [article objectForKey:@"publishedDate"];
    NSString *dateEdited = [date substringToIndex:16];

    cell.nameLabel.text  = title;
    cell.dateLabel.text  = dateEdited;

    NSURL *myURL=[NSURL URLWithString:[self.picturesArray objectAtIndex:indexPath.row]]; 
    NSData *myData1 = [[NSData alloc] initWithContentsOfURL:myURL] autorelease];
    UIImage *myImage = [[UIImage alloc] initWithData:myData1] autorelease]; 

    cell.imageView.image = myImage;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 2;

    return [cell autorelease];
}


You should not be downloading the image files on the main event loop.

Try to use some background downloader like SDWebImage.


You need to lazily load your images. This means loading them in another thread. Apple has excellent sample code that demonstrates this.


The first place I would check (and one that's easy to miss) is to make sure the reuse identifier of your cell is set correctly (to "Cell" in your case)in your CustomCell.xib file.

Example:

How To Make Scrolling UITableView Smoother?

To create your cell. assuming you have a nib called CustomCell.xib, you should create an IBOutlet in your view controller:

@property (nonatomic, retain) IBOutlet UITableViewCell * customCell;

and then in your CustomCell nib, set the File's Owner to be your view controller, and hook up the cell to the File's Owner custom cell outlet.

To create your cell, use the following code:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if(cell == nil)
    {
        [[NSBundle mainBundle] loadNibNamed: @"CustomCell" owner: self options: nil];
        cell = self.customCell;
        self.customCell = nil;
    }
    // Customise your cell here
    return cell;    
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜