UIImageView 滚动暂停一秒钟

Posted

技术标签:

【中文标题】UIImageView 滚动暂停一秒钟【英文标题】:UIImageView Scrolling halts for a second 【发布时间】:2013-05-01 06:14:51 【问题描述】:

我正在尝试使用 uiimage-from-animated-gif 将一些 GIF 加载到我的 UITableView 单元格中。但问题是每次我尝试从缓存中加载图像时,单元格在滚动之前都会暂停一点。

这是我使用的代码

postGif = (UIImageView *)[cell viewWithTag:104];

if ([[ImageCache sharedImageCache] DoesExist:post[@"gif"]] == true)

    image = [[ImageCache sharedImageCache] GetImage:post[@"gif"]];

    postGif.image = [UIImage animatedImageWithAnimatedGIFData:image];

else

    dispatch_queue_t backgroundQueue = dispatch_queue_create("cacheImage", 0);

    dispatch_async(backgroundQueue, ^

        NSData *imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:post[@"gif"]]];
        dispatch_async(dispatch_get_main_queue(), ^

            // Add the image to the cache
            [[ImageCache sharedImageCache] AddImage:post[@"gif"] image:imageData];

            NSIndexPath* ind = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
            [self.feedTableView beginUpdates];
            [self.feedTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:ind] withRowAnimation:UITableViewRowAnimationNone];
            [self.feedTableView endUpdates];
        );
    );


postGif.layer.cornerRadius = 2.0;
postGif.layer.masksToBounds = YES;

[cell.contentView addSubview:postGif]; 

我也尝试过后台队列。但是图像加载真的很慢。

if ([[ImageCache sharedImageCache] DoesExist:post[@"gif"]] == true)

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
                                             (unsigned long)NULL), ^(void) 
        NSData *image = [[ImageCache sharedImageCache] GetImage:post[@"gif"]];

        postGif.image = [UIImage animatedImageWithAnimatedGIFData:image];
    );

else

    dispatch_queue_t backgroundQueue = dispatch_queue_create("cacheImage", 0);

    dispatch_async(backgroundQueue, ^

        NSData *imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:post[@"gif"]]];
        dispatch_async(dispatch_get_main_queue(), ^

            // Add the image to the cache
            [[ImageCache sharedImageCache] AddImage:post[@"gif"] image:imageData];

            NSIndexPath* ind = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
            [self.feedTableView beginUpdates];
            [self.feedTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:ind] withRowAnimation:UITableViewRowAnimationNone];
            [self.feedTableView endUpdates];
        );
    );

我不确定我做错了什么。也许我没有掌握一个概念。

Maycoff 建议我不应该从后台队列修改用户界面对象(如 UIImageView)的属性,并且我需要在后台队列上创建 UIImage 的实例,有人可以向我解释一下这是什么我不抓?

提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

您之前代码中的问题是您从主队列上的 GIF 数据创建 UIImage。由于解码 GIF(尤其是具有多帧的 GIF)可能需要一些时间,因此您阻塞了主线程,这就是每次需要显示另一张图像时表格视图都会暂时停止滚动的原因。

您后面代码中的问题是您正在修改后台队列上UIImageViewimage 属性。您只能修改主队列上的用户界面对象。

您需要做的是在后台队列上创建UIImage,然后分派回主队列以更新UIImageViewimage 属性。因此:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
                                         (unsigned long)NULL), ^(void) 
    NSData *data = [[ImageCache sharedImageCache] GetImage:post[@"gif"]];
    UIImage *image = [UIImage animatedImageWithAnimatedGIFData:data];
    dispatch_async(dispatch_get_main_queue(), ^
        postGif.image = image;
    
);

【讨论】:

现在更有意义了 :) 非常感谢。但即使是现在我也不确定为什么它会冻结一会儿。 它对我来说非常适合这样。确保在后台线程上进行所有图像处理,并且只在主线程上进行 postGif.image = image。如果您将任何图像处理粘贴到主线程上,它将随机冻结滚动。

以上是关于UIImageView 滚动暂停一秒钟的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 动态更改 UIImageView 的图像

UIImage 视图从一个图像动画到下一个图像

为 UIImageView 手动缩放 UIImage

以编程方式向 UIImageView 添加约束

滚动视图不显示 UIView 和 UIImage

如何在滚动视图中使 UIImage 低于 UILabel 或 UITextView