UITableView对于块来说仍然很慢

时间:2014-02-16 18:31:11

标签: objective-c

所以我在我的应用程序中有一个tableView,它基本上运行一些用户朋友的名字和图像来自Facebook。 问题是,当我上下拖动tableView时,虽然我使用块来从Facebook上传图像,但它很慢并且不像它应该的那样平滑 - 所以它是异步的。 现在,在我实现了一个来自Facebook上传图像的块之后,它比块之前运行得更快 - 但仍然不够流畅。

有谁知道如何处理它? 这是我的一些代码:

cellForRowAtIndexPath:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"friendCell"];
   if (cell == nil) {
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                          reuseIdentifier:@"friendCell"];
      [friendsTableView reloadData];
   }

   //set data for user's friends images
   NSURL *url;
   NSString *stringID;
   stringID = [[NSString alloc]initWithFormat:@"https://graph.facebook.com/%@/picture?type=square",facebookFriendsID[indexPath.row] ];
   url = [NSURL URLWithString:stringID];

   //Calling block function to hendle user's friends images from facebook
   [self downloadImageWithURL:url :stringID :cell completionBlock:^(BOOL succeeded, UIImage *image) {
       if (succeeded) {
          cell.imageView.image = image;
       }
   }];

   //For friends name...
   cell.textLabel.text = facebookFriendsName[indexPath.row];
   cell.textLabel.font = [UIFont fontWithName:@"Noteworthy" size:17.0f];
   [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
   cell.imageView.layer.masksToBounds = YES;
   cell.imageView.layer.cornerRadius = 25.0;

   return cell;

}

和downloadImage块:

//For upload the images from Facebook asynchrony- using block.
- (void)downloadImageWithURL:(NSURL *)url : (NSString *)string : (UITableViewCell *)cell completionBlock:(void (^)(BOOL succeeded, UIImage *image))completionBlock
{

   NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
   [NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                           if ( !error )
                           {
                               UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];

                               completionBlock(YES,image);

                           } else{
                               completionBlock(NO,nil);
                           }
                       }];
}

谢谢! :)

2 个答案:

答案 0 :(得分:4)

您的代码有4个问题,所有问题都导致缓慢:

  1. 删除[friendsTableView reloadData]; - 您绝不应从cellForRowAtIndexPath:内部重新加载表格。
  2. 您不应该在完成块中引用cell

    [self downloadImageWithURL:url :stringID :cell completionBlock:^(BOOL succeeded, UIImage *image) {
        if (succeeded) {
            cell.imageView.image = image;
        }
    }];
    

    到您的图片下载时,cell可能已被重复使用并显示不同的内容。这可能会导致错误的头像图像出现。相反,请使用indexPath通过调用UITableViewCell *currentCell = [tableView cellForRowAtIndexPath:indexPath];获取当前单元格并在其上设置图像。

  3. 每次出现一个单元格时,您都在创建一个新的网络请求。如果用户滚动速度非常快,您将同时拥有大量网络请求。当滚动视图变慢时,您可能希望在scrollViewDidScroll:中启动网络请求。
  4. 您不会重复删除网络请求。如果用户非常快速地向上和向下滚动,他们将向同一URL生成大量网络请求。您需要缓存已下载的图像,并在已经建立网络请求时使用这些图像。*
  5. SDWebImage库已经解决了所有这些问题;你可能只是想用它而不是重新发明轮子。至少,值得阅读他们的代码:https://github.com/rs/SDWebImage


    * - NSURLCache可能会为您缓存图像,具体取决于服务器的cache-control标头。但即便如此,这个缓存很慢(它缓存NSData表示,而不是UIImage表示),NSURLConnection不会阻止你同时启动4个相同的请求。

答案 1 :(得分:1)

另外,请注意,您在请求完成块中从主线程第二次加载图像数据:

UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];

您需要使用completionHandler中的 NSData * data 参数 - ^(NSURLResponse *response, NSData *data, NSError *error)

UIImage *image = [UIImage imageWithData:data];

,正如Aaron Brager所说,你不需要重新发明轮子而不是像SDWebImage那样使用现成的解决方案。所以,只要你澄清它是如何运作的,这一切都很重要