简体   繁体   中英

TableView cells are being slow when scrolling

I have a tableView which shows a list of Facebook friends. I have an imageview within the cell which displays the profilePicture of the user. Using AFNetworking I call the new image and put a placeholder whilst loading.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"FbFriendCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

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

// Configure the cell...
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        NSDictionary *friend = (NSDictionary *)[self.searchResults objectAtIndex:indexPath.row];
        cell.textLabel.text = [friend valueForKey:@"name"];
    } else {
        NSDictionary *friend = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];

        UIImageView *profilePic = (UIImageView *)[cell.contentView viewWithTag:10];
        UILabel *displayName = (UILabel *)[cell.contentView viewWithTag:20];
        UIButton *playButton = (UIButton *)[cell.contentView viewWithTag:30];

        displayName.text = [friend valueForKey:@"name"];

        UIImage *defaultPhoto = [UIImage imageNamed:@"person.png"];
        NSString *urlString = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture", friend[@"id"]];
        NSURL *avatarUrl = [NSURL URLWithString:urlString];
        [profilePic setImageWithURL:avatarUrl placeholderImage:defaultPhoto];
        profilePic.contentMode = UIViewContentModeScaleAspectFit;
}

This is causing some speed/performance issues for the tableview. Does anyone know why this would be, is this setup correctly?

The cells are prototype cells created with a storyboard. I also have other code for the other objects in the cell, but removing the profile Picture section makes the cell perform normally so this appears to be the issue, just not sure why.

EDIT

UIImage *defaultPhoto = [UIImage imageNamed:@"person40x40.png"];
NSString *urlString = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?width=40&height=40", friend[@"id"]];

I have updated the pictures to fit the 40x40 image view but no difference. The iphone4 is slow to load the table cells. Compared to an iphone5 which is extremely smooth in scrolling.

Here is the heaviest in Time Profiler: 在此处输入图片说明

Looks like profilePic is the worst. This is because of the Data request from Facebook. I have changed the profilePic to only be the default Pic which is not a URL request and the table view is fine. So this is clearly an issue with performance for the setImageWithURL.

Looking at other questions it appears to be the best way to accomplish this though :- Best practices for managing facebook friends pics in iOS App

Any thoughts welcome

Auto-layout can cause some issues. Also, if you are resizing the images as they come in, that can cause slowness. The easiest way to tell for sure is to run Time Profiler (with Hide System Libraries and Show Obj-C Only checked). This will tell you where your slowness is coming from.

I now have few idea to improve your performance problem.

1) Requesting your friend improvment

From your edit it look like requestion your friend also take a fair amount of time:

NSDictionary *friend = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];

I'm sure you can cache most of this call with something like:

-(void)viewDidLoad{
    [super viewDidLoad];
    this.friendsInsensitive = [self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}



2) Web request improvement 1/2
reading few post about NSURLConnection and the event loop and blocking the main thread with async call

Let try something. Call the image web request in an other thread.

[...]
    UIImageView *profilePic = (UIImageView *)[cell.contentView viewWithTag:10];
    UILabel *displayName = (UILabel *)[cell.contentView viewWithTag:20];
    UIButton *playButton = (UIButton *)[cell.contentView viewWithTag:30];

    displayName.text = [friend valueForKey:@"name"];

    UpdateImgContainter *containter = [UpdateImgContainter alloc] initWithCell:cell andFriendId:friend[@"id"];

    [self performSelectorInBackground:@selector(requestImg:) withObject:containter];
}


-(void)requestImg:(UpdateImgContainter *)containter{
     UIImage *defaultPhoto = [UIImage imageNamed:@"person.png"];
     NSString *urlString = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture", containter.friendId];
     NSURL *avatarUrl = [NSURL URLWithString:urlString];
     [profilePic setImageWithURL:avatarUrl placeholderImage:defaultPhoto]; //warning it's not good practice to upload the UI from an other thread than MainThread
     profilePic.contentMode = UIViewContentModeScaleAspectFit;
}



2) Web request improvement 2/2 I just find out an other way to do it. And it's probably more reliable.
Download this LazyTableImages project from Apple itself. It was create exactly to teach the probleme you are facing.

At the end of the day I just think setImageWithURL: is maybe not that quick (?) and the point N°1 was probably part of your problem too. Looking a LazyTableImages project Apple simply use a NSURLConnection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM