티스토리 뷰

반응형

 

안녕하세요 :) Zedd입니다.

제곧내.

그냥 간단히 asset을 넣고, 해당 이미지를 요청하는 코드입니다, 

원래 왼쪽처럼 나와야하지만, 위 코드는 뭔가 2번씩 불려서 이미지가 중복되어있습니다.

일단 왜 그러는지 원인부터 보겠습니다. 

PhotoKit (2) - 미디어 가져오기에서도 설명한 내용인데, 문서가 정확하겠죠! 

(물론 위 글도 문서를 기반한 글입니다..!)

requestImage(for:targetSize:contentMode:options:resultHandler:)

의 discussion에 가시면 이유가 나와있습니다. 

1. 비동기 요청의 경우, Photos 프레임워크는 resultHandler블록을 2번 이상 호출 할 수 있다.

2. Photos는 블록을 호출하여 "고품질 이미지를 준비하는 동안" 일시적으로 표시하기에 적합한 저품질 이미지를 제공

3. 고품질 이미지가 준비되면, Photos프레임워크는 resultHandler를 다시 호출하여 이를 제공.

 

자..사진을 다시 봅시다.

제가 초록색으로 "여기까지"라고 표시해둔 부분을 잘 봅시다.

뭔가 여기까지의 사진은 품질이 낮아보이죠 좀 흐릿~~한 느낌..

2. Photos는 블록을 호출하여 "고품질 이미지를 준비하는 동안" 일시적으로 표시하기에 적합한 저품질 이미지를 제공

이때문입니다.

 

원인도 알았겠다...이를 해결해봅시다.

 

# 해결 1. 

제가 위에서 

1. 비동기 요청의 경우, Photos 프레임워크는 resultHandler블록을 2번 이상 호출 할 수 있다.

라고 그랬는데, 비동기 요청을 안하면 되겠죠!

이를 옵션으로 줄 수 있습니다.

이렇게요. 

let options = PHImageRequestOptions()
options.isSynchronous = true

이부분을 자세히 보시면 됩니다.

isSynchronous는 Photos에서 이미지 요청을 동기적으로 처리할지 여부를 결정하는 프로퍼티고, 기본값은 false입니다.

즉, 비동기로 요청하는게 기본값이라는거죠.

이걸 동기로 하겠다~ 라는 겁니다.

왜냐? 

"비동기 요청의 경우, Photos 프레임워크는 resultHandler블록을 2번 이상 호출 할 수 있다."니까,

아예 동기로 호출해서 resultHandler블록을 2번 이상 호출할 여지를 안주겠다는겁니다.

 

# 해결 2

requestImage(for:targetSize:contentMode:options:resultHandler:) 에 나와있는 내용입니다. 

 image manager가 이미지를 "full quality"로 캐시한 경우, Photos는 result Handler를 한번만 호출합니다.

2. Photos는 블록을 호출하여 "고품질 이미지를 준비하는 동안" 일시적으로 표시하기에 적합한 저품질 이미지를 제공

이라고 그랬죠.

아 나는 근데 저품질 이미지는 필요없고 시간이 얼마나 걸리든 고품질 이미지만 줘! 라고 요청할 수 있습니다.

let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat

이렇게요. 

deliveryMode는 기본값이 opportunistic인데요, 

highQualityFormat은, isSynchronous가 true일 때의 기본값입니다.

1. isSynchronous false임 && deliveryMode 따로 설정 안함 → deliveryMode == opportunistic

2. isSynchronous false임 && deliveryMode 설정 함 → deliveryMode == 설정한 deliveryMode

3. isSynchronous true임 && deliveryMode 따로 설정 안함 → deliveryMode == highQualityFormat

4. isSynchronous true임 && deliveryMode 따로 설정 함(예를들어 fastFormat) → deliveryMode == highQualityFormat

4번이 이해가 잘 안가실 수 있는데요, isSynchronous이 true면 다른 deliveryMode를 설정해도 효과가 없습니다.

자세한 내용은 highQualityFormat을 참고하세요. 

 

또는!!!

let options = PHImageRequestOptions()
options.deliveryMode = .fastFormat

이렇게 요청해도 resultHandler블록이 한번만 호출됩니다. 

고품질 이미지를 빠르게 로드할 수 없는 경우, resultHandler가 저품질 이미지를 제공하는 옵션입니다.

isSynchronous가 false인 경우에만 사용할 수 있어요.

(isSynchronous가 true && deliveryMode를 fastFormat으로 지정하는거 효과 x) 

 

# 해결 3

(참고로 options nil로 줬음)

resultHandler의 info부분에는 이미지 로드 결과에 대한 정보가 들어있습니다.

info의 PHImageResultIsDegradedKey가 true면

Photos프레임워크가 아직 고품질 이미지를 제공할 수 없기 때문에 저품질 이미지가 포함되어있다~ 이겁니다.

그래서 PHImageResultIsDegradedKey

let isDegraded = (info?[PHImageResultIsDegradedKey] as? Bool) ?? false
if isDegraded { return }

이런식으로 true면 리턴을 하여 해결 할수도 있습니다.

반응형