0

I have a CollectionView which displays some info about users. One of these items is a user avatar (100x100 png), which is loaded from our webserver. The problems is that it seems to me the view reloads the cells when they have gone outside the screen region. Every time I scroll the page it lags for a bit when the cells that were entirely outside the screen region enter the screen. It's not a really big problem on wifi, but on 3g this is really slow, plus it consumes bandwidth. Overall, it's just bad to handle data like this for my app. I want to load the data once and display it, and not have hundreds of webrequests when the user scrolls the page. Is there any way to load the cells once, and leave them like that until I update them manually? I don't do any updating yet, this is my current code:

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return numContacts;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];

    UILabel *contactName = (UILabel *)[cell viewWithTag:1];
    char *text = contactArray[indexPath.row].name;
    contactName.text = [NSString stringWithCString:text encoding:NSASCIIStringEncoding];

    NSData * presence = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"offline" ofType:@"png"]];
    UIImageView *presenceView = (UIImageView *)[cell viewWithTag:2];
    presenceView.image = [UIImage imageWithData: presence];

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"myWebServer",text]];
    NSData * avatar = [[NSData alloc] initWithContentsOfURL:url];
    UIImageView *avatarView = (UIImageView *)[cell viewWithTag:3];
    avatarView.image = [UIImage imageWithData: avatar];

    NSData *placeholder = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"avatar_unknown" ofType:@"png"]];
    [avatarView setImageWithURLRequest:[NSURLRequest requestWithURL:url] placeholderImage:[UIImage imageWithData:placeholder] success:nil failure:nil];

    return cell;
}
Kevin
  • 2,739
  • 33
  • 57

3 Answers3

0

You are loading the image data in the main queue, so you are blocking it, and thus the interface freezes.

Take a look at the answer to this question: how to send Asynchronous URL Request?

Community
  • 1
  • 1
The dude
  • 7,896
  • 1
  • 25
  • 50
  • Making the request async does not solve my problem. On 3g, the user's data bundle will still be used up. – Kevin Jul 22 '13 at 15:04
  • @Kevin you can also read image from bundle asynchronously and then after it's loaded set it in the main queue. – The dude Jul 23 '13 at 10:23
0

I think instead you should attempt to make one asynchronous service call when your View Controller is loaded to retrieve the data and store it (ex. in an NSMutableArray), because obviously making a service call everytime a cell is loaded is a poor solution. You could even just adjust your Contact custom object (I'm assuming you've created one to store relevant contact info) to include an image property to store the avatar Image. You can't 'load all the cells' because they're reloaded as they appear on the screen.

Chris Tetreault
  • 1,973
  • 13
  • 19
  • ok I will try that then. I wanted to keep my contact object as simple as possible, but I think adding an image is ok. – Kevin Jul 22 '13 at 16:47
0

I rewrote part of the code so I can retrieve all the images at the start, and just display them when my view loads. This solved both problems.

Kevin
  • 2,739
  • 33
  • 57