GCD - 用于更新UIImageView的主要vs后台线程 [英] GCD - main vs background thread for updating a UIImageView

查看:94
本文介绍了GCD - 用于更新UIImageView的主要vs后台线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是GCD的新手并阻止我进入它。

背景:我正在使用ALAssetsLibrary处理UIScrollView的延迟加载例程。当我的UIScrollView加载时,我用我的ALAssets的 aspectRatioThumbnails 填充它,然后当用户滚动时,我调用下面的例程来加载 fullScreenImage 当前正在显示的ALAsset。它似乎有用。

Background: I'm working on a lazy loading routine for a UIScrollView using the ALAssetsLibrary. When my UIScrollView loads I populate it with the aspectRatioThumbnails of my ALAssets and then as the user scrolls, I call the routine below to load the fullScreenImage of the ALAsset that is currently being displayed. It seems to work.

(如果有人有更好的延迟加载例程,请发表评论。我看了我能找到的所有内容以及WWDC视频但他们似乎更多地处理平铺或者比我需要的更复杂。

我的问题:我使用背景线程处理加载 fullScreenImage ,完成后我使用主线程将其应用于UIImageView。 我是否需要使用主线程?我已经看到所有UIKit更新都需要在主线程上进行,但我不确定是否适用于UIImageView。我认为它确实如此,因为它是一个屏幕元素,但后来我意识到我根本就不知道。

My question: I use a background thread to handle loading the fullScreenImage and when that is done I use the main thread to apply it to the UIImageView. Do I need to use the main thread? I've seen that all UIKit updates need to happen on the main thread but I am not sure if that applies to a UIImageView. I was thinking it does, since it is a screen element but then I realized that I simply didn't know.

- (void)loadFullSizeImageByIndex:(int)index
{
    int arrayIndex = index;
    int tagNumber = index+1;
    ALAsset *asset = [self.assetsArray objectAtIndex:arrayIndex];

    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        UIImage *tmpImage = [[UIImage alloc] initWithCGImage:asset.defaultRepresentation.fullScreenImage];

        if ([weakSelf.scrollView viewWithTag:tagNumber] != nil){

            dispatch_async(dispatch_get_main_queue(), ^{

                if ([weakSelf.scrollView viewWithTag:tagNumber]!= nil){
                    UIImageView * tmpImageView = (UIImageView*)[weakSelf.scrollView viewWithTag:tagNumber];
                    tmpImageView.image = tmpImage;
                }
            });
        }
    });
}


推荐答案

是的,你需要使用每当你触摸 UIImageView 或任何其他UIKit类时的主线程(除非另有说明,例如构造 UIImage s on background threads)。

Yes, you need to use the main thread whenever you're touching UIImageView, or any other UIKit class (unless otherwise noted, such as when constructing UIImages on background threads).

关于当前代码的一条评论:你需要将 weakSelf 分配给一个强大的使用前的局部变量。否则你的条件可能会通过,但是在你真正尝试使用它之前, weakSelf 可以被填没。它看起来像

One commentary about your current code: you need to assign weakSelf into a strong local variable before using it. Otherwise your conditional could pass, but then weakSelf could be nilled out before you actually try to use it. It would look something like

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    UIImage *tmpImage = [[UIImage alloc] initWithCGImage:asset.defaultRepresentation.fullScreenImage];

    __strong __typeof__(weakSelf) strongSelf = weakSelf;
    if ([strongSelf.scrollView viewWithTag:tagNumber] != nil){

        dispatch_async(dispatch_get_main_queue(), ^{
            __strong __typeof__(weakSelf) strongSelf = weakSelf;
            if ([strongSelf.scrollView viewWithTag:tagNumber]!= nil){
                UIImageView * tmpImageView = (UIImageView*)[strongSelf.scrollView viewWithTag:tagNumber];
                tmpImageView.image = tmpImage;
            }
        });
    }
});

从技术上讲,你不需要在后台队列的第一个条件中执行此操作,因为你'只有在那里取消引用它,但在触摸它之前将弱变量存储到强变量中总是一个好主意。

Technically you don't need to do this in the first conditional in the background queue, because you're only dereferencing it once there, but it's always a good idea to store your weak variable into a strong variable before touching it as a matter of course.

这篇关于GCD - 用于更新UIImageView的主要vs后台线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆