UIImage initWithData: blocking UI thread from asyn

2020-08-04 06:42发布

问题:

The following code is blocking UI (can't tap another tab until images finish loading).

I have verified it is the UIImage *imageToShow = [[UIImage alloc] initWithData:data]; call that is the culprit by commenting that line out and keeping the download (which I know happens asynchronously and calls completion handler on main thread).

In the case where only the initWithData: line is commented, the UI response is fine. But how can that line be the line holding up the UI if it is clearly dispatched in background?

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    ...

    [objectStore getFileInContainer:@"public_images" filename:filename completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            UIImage *imageToShow = [[UIImage alloc] initWithData:data];
            dispatch_async(dispatch_get_main_queue(), ^{
                collectionImageView.image = imageToShow;
            });
        });
    }];

    ...
}

回答1:

UIImage doesn't read and decode the image until the first time it's actually used/drawn. To force this work to happen on a background thread, you have to use/draw the image on the background thread before doing the main thread -setImage: call. Many folks find this counter-intuitive. I explained this in considerable detail in another answer.



回答2:

The part most likely to cause the UI to hang is the actual setting of the image to the image view, especially if the image is large, because this does (and must) occur on the main thread.

I would suggest resizing or scaling down the image first while you are still operating in the background thread. Then once you have the image resized, hop back on the main thread and assign it to the ``imageView.image```.

Here is a simple example of one way to resize a UIImage: Resize UIImage by keeping Aspect ratio and width