【问题标题】:Asynchronously download images for UITableView using NSURLConnection使用 NSURLConnection 异步下载 UITableView 的图像
【发布时间】:2016-03-28 09:41:35
【问题描述】:

我有一个带有 customCells 的 TableView,当用户按下某个单元格上的开始按钮时,加载开始。有很多这样的单元,所以我需要并行(异步)实现这个下载。 对于图像下载和更新表格视图中的单元格,我使用下一个代码:

#define myAsyncQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

我将此方法包含在异步队列中,我认为应该启用图像的并行下载。 - (void)didClickStartAtIndex:(NSInteger)cellIndex withData:

    (CustomTableViewCell*)data
    {
 dispatch_async(myAsyncQueue, ^{        
self.customCell = data;
        self.selectedCell = cellIndex;
        ObjectForTableCell* tmp =[self.dataDictionary objectForKey:self.names[cellIndex]];

        NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:tmp.imeageURL]
                                                    cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                timeoutInterval:60.0];
        self.connectionManager = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
       }); 
    }
    -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
          self.urlResponse = response;

        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
        NSDictionary *dict = httpResponse.allHeaderFields;
        NSString *lengthString = [dict valueForKey:@"Content-Length"];
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        NSNumber *length = [formatter numberFromString:lengthString];
        self.totalBytes = length.unsignedIntegerValue;

        self.imageData = [[NSMutableData alloc] initWithCapacity:self.totalBytes];
    }

    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
           [self.imageData appendData:data];
        self.customCell.progressView.progress = ((100.0/self.urlResponse.expectedContentLength)*self.imageData.length)/100;
          float per = ((100.0/self.urlResponse.expectedContentLength)*self.imageData.length);
        self.customCell.realProgressStatus.text = [NSString stringWithFormat:@"%0.f%%", per];

    }

   I tried to set this block to queue - main queue - cause its the place where image is already downloaded,

        -(void)connectionDidFinishLoading:(NSURLConnection *)connection
        {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.customCell.realProgressStatus.text = @"Downloaded";

            UIImage *img = [UIImage imageWithData:self.imageData];
            self.customCell.image.image = img;
            self.customCell.tag = self.selectedCell;
    });
            [self.savedImages setObject:img forKey:self.customCell.nameOfImage.text];
            NSNumber *myNum = [NSNumber numberWithInteger:self.selectedCell];
            [self.tagsOfCells addObject:myNum];
       }

没有所有队列(当我评论它时)一切正常 - 但只有 1 个下载。 但是,当我尝试使用队列实现代码时,它不会下载任何东西。我知道我做错了,但我无法定义它。

非常感谢您提前提供的任何帮助。

【问题讨论】:

  • @Fahim,谢谢你的建议,我正在学习,想自己实现它,没有任何第三方库,至少尝试自己做

标签: ios objective-c uitableview asynchronous


【解决方案1】:

如果您希望从基础开始,我想您应该从NSURLSession 开始,因为NSURLConnection 大多数实现已被弃用,并且在 iOS 9 之后将不再可用。完整参考 URL Session Programming Guide 和 @987654324 @

回到你的问题,你应该从教程中做类似的事情

// 1
NSURLSessionDownloadTask *getImageTask =
[session downloadTaskWithURL:[NSURL URLWithString:imageUrl]

    completionHandler:^(NSURL *location,
                        NSURLResponse *response,
                        NSError *error) {
        // 2
        UIImage *downloadedImage =
          [UIImage imageWithData:
              [NSData dataWithContentsOfURL:location]];
      //3
      dispatch_async(dispatch_get_main_queue(), ^{
        // do stuff with image
        _imageWithBlock.image = downloadedImage;
      });
}];

// 4
[getImageTask resume];

但我个人的建议是 AFNetworking,它最适合 iOS 网络,并在 iOS 应用程序世界中广泛使用/测试。

使用 AFNetworking 下载图片

[_imageView setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://i.imgur.com/fVhhR.png"]]
                      placeholderImage:nil
                               success:^(NSURLRequest *request , NSHTTPURLResponse *response , UIImage *image ){
                                   NSLog(@"Loaded successfully: %d", [response statusCode]);
                               }
                               failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
                                   NSLog(@"failed loading: %@", error);
                               }
    ];

编辑:使用并发进行异步下载

// get main dispact queue
dispatch_queue_t queue = dispatch_get_main_queue();
// adding downloading task in queue using block
dispatch_async(queue, ^{
  NSData* imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]];
  UIImage* image = [[UIImage alloc] initWithData:imageData];
  // after download compeletes geting main queue again as there can a possible crash if we assign directly
  dispatch_async(dispatch_get_main_queue(), ^{
    _imageWithBlock.image = image;
  });
});

【讨论】:

  • 非常感谢,是的,我知道 NSURLConnection 已被弃用,我将转到 NSURLSession,但目前我需要在当前项目中解决此问题
  • 非常感谢您的帮助))。
【解决方案2】:

使用来自Apple 的示例代码来解决您的延迟加载问题。

【讨论】:

    猜你喜欢
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多