Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UITableView中的图像不断重新加载,滚动时错误图像闪烁_Ios_Objective C_Xcode_Uitableview_Ios8 - Fatal编程技术网

Ios UITableView中的图像不断重新加载,滚动时错误图像闪烁

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

我创建了一个UITableView,它根据URL请求填充每个单元格。我使用了“dispatch_queue”来防止UItableView冻结。由于某种原因,当我在UITableView中滚动时,图像会闪烁并消失,然后填充错误的单元格一秒钟,直到修复它们。这是我的密码。我正在使用restkit提取提要

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未完成,则现在将有两个块希望将其图像放置到同一单元上。 导致以下两种情况:

  • 块0首先完成,然后是块10
  • 块10首先完成,然后块0完成
  • 这就是导致“闪烁”的原因

    然后想象一下在几秒钟内滚动1000个单元格:)

    解决方案

    您需要能够取消排队块,以便重新使用单元格


    我会使用例如或。

    你是怎么说的。在另一个线程中捕获图像,以防止冻结。在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项目添加一个依赖项,然后使用我在回答中提供的代码。非常感谢您的支持