Ios UITableView中的图像不断重新加载,滚动时错误图像闪烁
我创建了一个UITableView,它根据URL请求填充每个单元格。我使用了“dispatch_queue”来防止UItableView冻结。由于某种原因,当我在UITableView中滚动时,图像会闪烁并消失,然后填充错误的单元格一秒钟,直到修复它们。这是我的密码。我正在使用restkit提取提要Ios UITableView中的图像不断重新加载,滚动时错误图像闪烁,ios,objective-c,xcode,uitableview,ios8,Ios,Objective C,Xcode,Uitableview,Ios8,我创建了一个UITableView,它根据URL请求填充每个单元格。我使用了“dispatch_queue”来防止UItableView冻结。由于某种原因,当我在UITableView中滚动时,图像会闪烁并消失,然后填充错误的单元格一秒钟,直到修复它们。这是我的密码。我正在使用restkit提取提要 customCell.customCellTextLabel.text = [NSString stringWithFormat:@"%@",feedO.title]; NSString
customCell.customCellTextLabel.text = [NSString stringWithFormat:@"%@",feedO.title];
NSString *string = [NSString stringWithFormat:@"%@",feedO.body];
NSURL *urlString;
NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:string options:0 range:NSMakeRange(0, [string length])];
for (NSTextCheckingResult *match in matches) {
if ([match resultType] == NSTextCheckingTypeLink) {
urlString = [match URL];
NSLog(@"found Body URL: %@ and title %@", urlString,feedO.title);
}
}
dispatch_queue_t imageQueue = dispatch_queue_create("imageDownloader",nil);
dispatch_async(imageQueue, ^{
NSData *data = [[NSData alloc] initWithContentsOfURL:urlString];
dispatch_async(dispatch_get_main_queue(), ^{
customCell.customCellImageView.image = [UIImage imageWithData: data];
});
});
return customCell;
您的代码缺少一行,这是我添加的 customCell.customCellImageView.image=nil强>
customCell.customCellTextLabel.text = [NSString stringWithFormat:@"%@",feedO.title];
NSString *string = [NSString stringWithFormat:@"%@",feedO.body];
NSURL *urlString;
customCell.customCellImageView.image =nil;
NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:string options:0 range:NSMakeRange(0, [string length])];
for (NSTextCheckingResult *match in matches) {
if ([match resultType] == NSTextCheckingTypeLink) {
urlString = [match URL];
NSLog(@"found Body URL: %@ and title %@", urlString,feedO.title);
}
}
dispatch_queue_t imageQueue = dispatch_queue_create("imageDownloader",nil);
dispatch_async(imageQueue, ^{
NSData *data = [[NSData alloc] initWithContentsOfURL:urlString];
dispatch_async(dispatch_get_main_queue(), ^{
customCell.customCellImageView.image = [UIImage imageWithData: data];
});
});
return customCell;
原因是,
UITableView
正在重用创建的单元格。
首先,它创建了10个CustomCell
类
单元格0单元1
…
第9单元 通过创建这10个单元格,它将启动10个异步调用来获取图像 块0->单元格0
块1->单元格1
…
第9区->第9单元 如果在10次下载全部完成后才滚动,这将很好地工作 但一旦开始滚动,
UITableView
将开始重用创建的单元格并启动新的下载
因此,首先它可能会重用单元0并创建块10->单元0
如果在拾取单元0以供重用时块0未完成,则现在将有两个块希望将其图像放置到同一单元上。
导致以下两种情况:
我会使用例如或。你是怎么说的。在另一个线程中捕获图像,以防止冻结。在tableView中,单元格被重用,在一个后台线程中捕获新照片时,在主线程中返回带有前一张照片的单元格。 在下面的代码中,我修复了它并提供了更好的解释: customCell.customCellTextLabel.text=[NSString stringWithFormat:@“%@”,feedO.title]
NSString *string = [NSString stringWithFormat:@"%@",feedO.body];
NSURL *urlString;
NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:string options:0 range:NSMakeRange(0, [string length])];
for (NSTextCheckingResult *match in matches) {
if ([match resultType] == NSTextCheckingTypeLink) {
urlString = [match URL];
NSLog(@"found Body URL: %@ and title %@", urlString,feedO.title);
}
}
// Here you need, at least quit the previous imagen, is better if you implement
// and activity indicator (here start), and also you should implement some imagen cache.
customCell.customCellImageView.image = nil;
// Apart from here, go to another thread.
dispatch_queue_t imageQueue = dispatch_queue_create("imageDownloader",nil);
dispatch_async(imageQueue, ^{
// this operation is slowly that return a cell, this happens after [1]
NSData *data = [[NSData alloc] initWithContentsOfURL:urlString];
dispatch_async(dispatch_get_main_queue(), ^{
//If you implement and activity indicator stop here.
customCell.customCellImageView.image = [UIImage imageWithData: data];
});
});
// [1] the cell is returned before the image is ready.
return customCell;
以上答案是正确的。但不需要在单元格中为行下载图像。您可以在ViewWillDisplay或ViewDidLoad中加载表之前下载图像,这符合您的要求 每次滚动表格时,图像将再次下载。为了防止这种情况,我希望您从缓存中获取图像,并直接在imageview中设置。所以按照你的代码。如果您从0索引滚动到10,则cell将下载所有10个cell的图像。之后,如果您再次滚动10到索引0。然后图像将再次下载 您可以使用()下载映像异步。这很容易,也很快 我更喜欢这个库,因为它可以处理你的缓存。只需写下面的代码
#import "UIImageView+WebCache.h"
// in cellForRowAtIndexPath.
[customCell.customCellImageView sd_setImageWithURL: [NSURL URLWithString:urlString]];
删除下面的代码
dispatch_queue_t imageQueue = dispatch_queue_create("imageDownloader",nil);
dispatch_async(imageQueue, ^{
NSData *data = [[NSData alloc] initWithContentsOfURL:urlString];
dispatch_async(dispatch_get_main_queue(), ^{
customCell.customCellImageView.image = [UIImage imageWithData: data];
});
});
<>也许这会对你有帮助。 你应该考虑使用这个库SDWebMead,在这里可以找到这样的问题。它可以非常轻松地处理远程映像的异步下载和缓存 最简单的安装是使用CoCoapod完成的 CocoaPods()是Objective-C的依赖关系管理器,它自动化并简化了在项目中使用第三方库的过程。 有关更多详细信息,请参阅入门部分 在你的播客文件中使用
platform :ios, '6.1'
pod 'SDWebImage', '~>3.6'
安装SDWebImage的依赖项后,只需在视图控制器中使用以下行:
#import <SDWebImage/UIImageView+WebCache.h>
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// Here we use the new provided setImageWithURL: method to load the web image
[cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
cell.textLabel.text = @"My Text";
return cell;
}
#导入
...
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
静态NSString*MyIdentifier=@“MyIdentifier”;
UITableViewCell*单元格=[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
如果(单元格==nil)
{
单元格=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier]自动释放];
}
//这里我们使用新提供的setImageWithURL:方法来加载web图像
[cell.imageView setImageWithURL:[NSURL URLWithString:@]http://www.domain.com/path/to/image.jpg"]
占位符图像:[UIImage ImageName:@“placeholder.png”];
cell.textlab.text=@“我的文本”;
返回单元;
}
无法解决此问题,因为这也是一个时间问题。哦,好的,有什么方法可以防止此问题吗?此外,当我滚动回顶部时,它似乎正在重新加载所有图像等…?点击按钮太快,更新有一个建议。当你每次滚动时,你的手机将再次下载图像。我更喜欢使用()。这是一个很好的库,可以异步下载映像,还可以维护缓存。因为根据你的代码。如果您的手机下载索引为0到5的图像。当您再次返回索引0到5时,您的图像将再次下载。我以前尝试过此操作,但没有发现需要将SDWebImage中的哪些文件添加到我的项目中?我是否只将名为“SDWebImage”的文件夹添加到我的项目中而不添加其他内容?@burrgg yes在项目中添加文件夹名称SDWebImage
。添加“ImageIO.framework”,并将其他链接器标志设置为-ObjC
和#导入“UIImageView+WebCache.h”
。你就完了。如果您知道如何安装,也可以安装pod文件。@Burggg使用pod'SDWebImage',“~>3.6”
安装pod。谢谢您的帮助,我不太确定链接器标志是什么is@burrGGG单击项目>生成设置(第四个选项)>其他链接器标志>双击该链接器>单击下面的+按钮>写入-ObjC
>按enter键。:)我以前尝试过这个,但我不清楚需要将SDWebImage中的哪些文件添加到我的项目中?我是否只向项目中添加名为“SDWebImage”的文件夹而不添加其他内容?最简单的方法是在项目()中使用pod来管理第三方库的依赖关系。只需在您的pod文件中为完整的SDWebImage项目添加一个依赖项,然后使用我在回答中提供的代码。非常感谢您的支持