iOS

PHCachingImageManager requestImage 이미지 중복 SWIFT TASK CONTINUATION MISUSE

삼쓰_웅쓰 2023. 2. 7. 19:17
반응형

PHCachingImageManager.default().requestImage

PHAsset 에서 이미지를 가져올 때 해당 메서드를 사용합니다.
무심코 아래와 같이 option 없이 사용할 수 있는데요

PHCachingImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: nil) { image, info in
    if let image = image {
        continuation.resume(returning: image)
    }
}

 

이럴 때 주의해야 할 점이 있습니다.

이 함수는 기본적으로 비동기적으로 동작합니다.
비동기적으로 사용했을 때 Photos는 고화질 이미지를 준비할 동안 일시적으로 저화질 이미지를 제공한다고 하네요.
따라서 이미지를 (result handler block) 을 여러 번 반환할 수 있습니다. (거의 그렇더군요;;)

그래서! 분명 asset 개수보다 더 많은 중복 이미지 (저화질 이미지, 고화질 이미지 섞여서)가 생길 수 있습니다.

비동기로 호출한다면 이런 문제를 막기 위해 아래와같이 동기 옵션을 추가해주면 됩니다.

let option = PHImageRequestOptions()
option.isSynchronous = true

PHCachingImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: options) { image, info in
    if let image = image {
        continuation.resume(returning: image)
    }
}

 

뿐만 아니라 제 경우 swift 동시성을 사용할 때 문제가 발생했는데요,
requestImage 의 result completion handler 를 처리하기 위해 아래와 같이 사용하려고 했었답니다.

func loadImage(asset: PHAsset, size: CGSize, resizeMode: PHImageRequestOptionsResizeMode = .exact, deliveryMode: PHImageRequestOptionsDeliveryMode? = nil) async -> UIImage? {
    return await withCheckedContinuation { continuation in
        PHCachingImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: nil) { image, info in
            if let image = image {
                continuation.resume(returning: image)
            }
        }
    }
}

 

그랬더니 아래와 같은 에러가 발생했습니다 ;;
아직 동시성을 깊게 공부하지 못하고 막 걸음마 떼는 수준이라 적잖이 당황했었는데요,,,

Thread 1: Fatal error: SWIFT TASK CONTINUATION MISUSE: loadImage(asset:size:resizeMode:deliveryMode:) tried to resume its continuation more than once, returning Optional(<UIImage:0x600003ca7600 anonymous {1668, 2500} renderingMode=automatic(original)>)!

 

continuation 을 여러 번 resume 해서 발생했다고 하는데 뭘 잘못했나 한참 고민했네요..
위에서 설명드린 것처럼 PHCachingImageManager.default().requestImage 가 이미지를 여러 번 호출해서 문제가 됐었던 것 같아요.

도움이 되셨다면 좋겠네요.
읽어주셔서 감사합니다!

 

 

 

반응형