0

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: enter image description here

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

Community
  • 1
  • 1
StuartM
  • 6,743
  • 18
  • 84
  • 160
  • 1
    How big are the profile pictures? – Patrick Tescher Jul 15 '13 at 23:34
  • what if you remove the profilePic? Is it quicker? – Martin Magakian Jul 16 '13 at 05:34
  • It might help, setImageWithURL: come from AFNetworking library and it's loading the image asynchronously: http://engineering.gowalla.com/AFNetworking/Categories/UIImageView(AFNetworking).html#//api/name/setImageWithURL: – Martin Magakian Jul 16 '13 at 05:43
  • @PatrickTescher checkout https://graph.facebook.com/martin-magakian/picture the requested pictures are pretty small – Martin Magakian Jul 16 '13 at 05:45
  • @MartinMagakian If you want to use it Facebook has its own profile image view class: https://developers.facebook.com/docs/reference/ios/3.5/class/FBProfilePictureView It automatically chooses the appropriate image to download, manages the url connection, etc. – Patrick Tescher Jul 16 '13 at 16:46
  • Is the profile image view not for a single image view for the users profile picture as opposed to a table view of all friends with multiple profile pictures? – StuartM Jul 16 '13 at 16:53
  • @MartinMagakian - Is there an issue with these being async? It is expected if they queue up to 500 friends profile pics being downloaded? – StuartM Jul 16 '13 at 16:54
  • @StuartM it's the right things those request are asyn. Otherwith it would wait for the to download before continuing to scroll. 500 should be ok. More over the code above will be execute **during** scrolling. More you scroll more you add request – Martin Magakian Jul 16 '13 at 16:56
  • @StuartM is it quicker if your remove the image and the image request from your code? – Martin Magakian Jul 17 '13 at 03:44
  • @MartinMagakian - actually after testing some more I am noticing the issue mainly on the iphone4. The iphone5 has no problem at all, could it be that the phone is that slow compared? Is it common to find the iphone4 is slugish, it seems to be through out the app. There is nothing but this on the phone and nothing else running. Am I that used to a faster phone....? – StuartM Jul 17 '13 at 19:39
  • The iPhone5 is definitely quicker, but I'm sure we can find a way to speed it up for iPhone4. @StuartM can your remove this line "profilePic setImageWithURL: [...]" and tell us if it's still slow. More information would be appreciate. – Martin Magakian Jul 18 '13 at 02:06
  • @MartinMagakian - Yes much quicker without that line, sorry I had tested that just wasn't sure why it was causing the issue. What other information are you looking for and I will gladly provide it? Thank you – StuartM Jul 18 '13 at 16:47
  • @StuartM I'm going to bed but tomorrow I will try few idea and hopefully I will give you an answer :-) – Martin Magakian Jul 18 '13 at 17:30
  • @MartinMagakian - Updated the question with an edit with much more information... thanks – StuartM Jul 18 '13 at 22:33

2 Answers2

0

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.

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
0

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.

Community
  • 1
  • 1
Martin Magakian
  • 3,746
  • 5
  • 37
  • 53