본문 바로가기
감정일기(가칭)

📌 iOS 파일 선택(UIDocumentPicker) 시 이미지가 안 보이던 문제 해결하기

by 밤새는 탐험가89 2025. 11. 15.
728x90
SMALL

일기를 작성하는 화면에서,
사용자가 사진 앱 뿐만 아니라 *파일 앱(파일 보관함)*에서도

이미지를 선택해서 첨부할 수 있도록 구현하는 기능을 만들었다.

 

하지만 파일 앱에서 png/jpg 파일을 선택하면 다음과 같은 문제가 발생했다.


❗️문제 상황

1) 파일을 선택하면 콘솔에 아래와 같은 에러가 출력됨

Failed to associate thumbnails for picked URL ... 
QLThumbnailErrorDomain Code=102
Generation not found

 

2) 파일을 선택한 후 컬렉션뷰(UIImage 목록)에 아무것도 표시되지 않음

사진 앱에서 선택하면 잘 나오는데,
파일 앱에서 선택한 이미지는 전혀 안 나타나는 문제가 있었다.


🔍 문제 원인 파악

문제의 핵심은 여기였다.

let coordinated = url.startAccessingSecurityScopedResource()
defer { url.stopAccessingSecurityScopedResource() }

guard coordinated else { return }   // ❗️여기 때문에 전체 코드가 실행되지 않음

 

- 파일 앱이나 iCloud Drive 내에 있는 파일은
종종 security-scoped resource 접근 권한을 정확하게 가져오지 못하는 경우가 있음.

 

- 그런 경우 startAccessingSecurityScopedResource()가 false를 반환한다.

 

- 그러면 guard coordinated else { return }에 걸려서
아래 코드(Data 로드, UIImage 변환, appendImage)까지 실행되지 않는다.

 

즉, 컬렉션뷰에 이미지가 안 나오는 이유는
이미지 로드 자체가 아예 실행되지 않았기 때문!

 

❗️그럼 QLThumbnailErrorDomain 에러는?

이건 부가적인 에러 로그일 뿐, 기능에 직접적인 문제는 아니다.

파일 앱이 내부적으로 파일 썸네일을 만들다가 실패하는 로그일 뿐이며,
이미지를 읽어오는 기능 자체는 여전히 문제없이 가능하다.


✔️ 해결 방법

startAccessingSecurityScopedResource()
“되면 좋고, 안 돼도 괜찮은 옵션”이라고 보면 된다.

 

그래서 아래와 같은 패턴으로 변경해주어야 한다.

func documentPicker(_ controller: UIDocumentPickerViewController,
                    didPickDocumentsAt urls: [URL]) {
    
    guard let url = urls.first,
          let cell = currentPhotoCell else { return }
    
    // security-scoped permission 요청 (실패해도 괜찮음)
    let coordinated = url.startAccessingSecurityScopedResource()
    defer {
        if coordinated { url.stopAccessingSecurityScopedResource() }
    }
    
    do {
        let data = try Data(contentsOf: url)
        
        if let originalImg = UIImage(data: data),
           let image = originalImg.resized(maxWidth: 1200) {
            
            // 성공적으로 이미지 추가
            cell.appendImage(image)
            
        } else {
            showInvalidFileAlert()
        }
        
    } catch {
        print("파일 로드 실패: \(error.localizedDescription)")
        showInvalidFileAlert()
    }
}

🔑 핵심 포인트 요약

Before (문제 발생) After (문제 해결)
guard coordinated else { return } 때문에 파일 로드가 아예 안 됨 coordinated는 실패해도 상관 없이 이미지 로드 시도
파일 앱의 이미지가 대부분 coordinated = false coordinated 실패해도 Data(contentsOf:)는 정상 동작
컬렉션뷰가 업데이트되지 않음 appendImage가 정상 실행되어 UI 업데이트됨
728x90
LIST