ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • PHCachingImageManager requestImage 이미지 중복 SWIFT TASK CONTINUATION MISUSE
    iOS 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 가 이미지를 여러 번 호출해서 문제가 됐었던 것 같아요.

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

     

     

     

    반응형

    댓글

Designed by Tistory.