GCD - main vs background thread for updating a UIImageView

前提是你 提交于 2019-11-28 09:06:23

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).

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.

If you need to render the image in UIImageView, you need to do this in main thread. It will not work unless you do it in main queue as shown in your code. Same is the case with any UI rendering.

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

As per Apple documentation,

Threading Considerations: Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the UIView class from code running in the main thread of your application. The only time this may not be strictly necessary is when creating the view object itself but all other manipulations should occur on the main thread.

Yes you need to use the main thread, since any UI changes needs to be done in the main thread.

As for using the GCD it is used to take the advantage of the Multi Cores on the device. As for the strong and weak self

strong self: you might want a strong self, for in you code

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
(<your class> *) *strongSelf = weakSelf;
    UIImage *tmpImage = [[UIImage alloc] initWithCGImage:asset.defaultRepresentation.fullScreenImage];

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

        dispatch_async(dispatch_get_main_queue(), ^{

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

say you have a view which make a API call and it takes time, so you switch back to another view but you still want the image to be downloaded then use strong since the block owns the self so the image is downloaded.

weak self: if in the above situation you dont want the image to download once you move to a different view then use weak self, since the block doesn't own any self.

If you will not use strongSelf in the code suggested by Kevin Ballard then it might lead to a crash because of weak getting nilled out.

Also a good practice would be to even check for strong being non nil at the point of creating

strongSelf = weakSelf

   if(strongSelf)
   {
       // do your stuff here 
   }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!