我正在制作应用..
我需要从服务器下载很多图片,但我不知道该怎么做
以前是通过以下一些文章
来做到这一点的目前正面临一些问题 当滚动图像闪烁并一直改变时。快速向上滚动时,所有图像都是错误的。我该怎么办?
- (void)downloadImageWithURL:(NSURL *)url 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 alloc] initWithData:data];
completionBlock(YES,image);
} else{
completionBlock(NO,nil);
}
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"venue";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
Venue *venue = ((Venue * )self.venues[indexPath.row]);
if (venue.userImage) {
cell.imageView.image = venue.image;
} else {
// set default user image while image is being downloaded
cell.imageView.image = [UIImage imageNamed:@"default.png"];
// download the image asynchronously
[self downloadImageWithURL:venue.url completionBlock:^(BOOL succeeded, UIImage *image) {
if (succeeded) {
// change the image in the cell
cell.imageView.image = image;
// cache the image for use later (when scrolling up)
venue.image = image;
}
}];
}
}
**任何最佳方式建议**
答案 0 :(得分:1)
我在您的代码中看到了一些问题,所以让我先给出一个您需要的最小例子:
- (void)downloadImageFrom:(NSURL *)path completion:(void (^)(UIImage *image))completionBlock {
dispatch_queue_t queue = dispatch_queue_create("Image Download", 0);
dispatch_async(queue, ^{
NSData *data = [[NSData alloc] initWithContentsOfURL:path];
dispatch_async(dispatch_get_main_queue(), ^{
if(data) {
completionBlock([[UIImage alloc] initWithData:data]);
} else {
completionBlock(nil);
}
});
});
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = ...; // Create my own cell
NSString *imageURL = ...; // Get from my model
cell.imageURLString = imageURL;
[self downloadImageFrom:[NSURL URLWithString:imageURL] completion:^(UIImage *image) {
if(cell.imageURLString == imageURL) {
cell.imageView.image = image;
}
}];
return cell;
}
首先,下载时(无论您使用什么)确保您使用正确的线程。我使用最简单的工具来下载使用NSData
的远程图像,并且只要您的请求不需要额外的数据(如凭据),它就会很好用。您没有理由更改它,但确保在主线程上调用完成。
接下来您遇到的问题是多线程加上单元格出列问题。在表格视图中,将重用相同的单元格。向下滚动从屏幕向上移动的单元格将显示在底部。这是为了获得表现。
现在因为您向上和向下滚动并且图像异步加载,可能会调用完成块if (succeeded) {
以查看它看起来不正确的单元格。您需要做的是检查通话是否仍然有效。
因此,您应该对您的单元格进行子类化,并至少添加一些标识符,例如imageURLString
。您在进行调用之前设置了获取图像,然后在完成时再次检查单元标识符是否仍然相同。如果不是,那么您的单元格已被重用,下载的图像将被丢弃。
这也意味着你应该创建某种图像缓存。这样一个抛弃的图像并没有被丢弃,而是被缓存,如果出现相同的单元格,则不会再次发生下载。