Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save skyofdwarf/c10056155a0c51fd5d6add1d6b868896 to your computer and use it in GitHub Desktop.
Save skyofdwarf/c10056155a0c51fd5d6add1d6b868896 to your computer and use it in GitHub Desktop.
iOS 14>=, '선택한 사진' 권한 선택 시 handler 미호출 이슈 및 대응

iOS 14 >=, '선택한 사진' 권한 선택 시 handler 미호출 이슈 및 대응

이슈

PHPhotoLibrary.requestAuthorization(:_) 또는 PHPhotoLibrary.requestAuthorization(for:handler:) 로 사진권한 요구 시 사용자가 '사진 선택'을 고르면, 사용할 사진을 고를 수 있도록 시스템 이미지피커가 기본 모달스타일(UIModalPresentationStyle.pageSheet)로 뜨게 된다. 이 때 '취소/완료' 버튼을 누르면 전달한 handler가 호출되지만, 피커를 아래로 끌어당겨(pull to dismiss?) 닫게 되면 handler가 호출되지 않는 이슈가 있다.

같은 이슈의 질문을 찾았지만 같은 이슈를 고민하는 사람이 있다는걸로 만족.. https://stackoverflow.com/questions/65351479/phphotolibrary-requestauthorizationfor-handler-does-not-calls-handler-block

커스텀 앨범

커스컴 앨범처럼 PHAsset.fetchAssets(...)를 바로 호출할 경우 사진권한이 .notDetermined이면 자동으로 사진권한 요구팝업이 뜨게 되는데 이 때는 사용자가 확인/취소 버튼이 아닌 피커를 땡겨 닫아버려도(pull to dismiss) fetchAssets(...)가 빈 목록을 리턴할테고 이 빈 목록으로 UI로 대응이 가능할 것이다.

권한안내 화면

하지만, 커스텀한 권한 안내화면을 보여주고 확인 버튼을 눌러 PHPhotoLibrary.requestAuthorization(...)로 권한요구팝업을 띄운 경우는 사용자가 피커를 땡겨 닫을 경우 handler 호출이 되지 않으니 이후 진행을 할 수 가 없다(PHPhotoLibraryChangeObserver 도 취소/확인의 경우만 반응한다).

케이스 조사 및 벤치마킹

그렇다면 다른 앱들은 어떻게 처리했을까?

  1. Instagram: 권한안내 화면을 사용하고 있다. 위 내용과 동일하게 피커를 땡겨 닫으면 안내화면이 그대로 남아있고 '계속'버튼을 다시 눌러도 아무 반응이 없다(2022/06/23 확인)
  2. Facebook: 권한안내 화면을 사용하고 있다. 위 내용과 동일하게 피커를 땡겨 닫으면 안내화면이 그대로 남아있지만 버튼을 다시 누르면 안내화면이 사라지고 다음 진행이 된다(빈 목록의 커스텀 앨범).
  3. 카카오톡: 권한안내 화면이 있었는지 까먹었는데 상관없이 이미지피커가 .fullScreen 모드로 떠서 pull to dismiss가 불가능하다. 오우

대응

따라서 권한안내 화면을 사용하는 경우 대응방법으로 2가지를 생각해 볼 수 있다.

  1. Facebook처럼 안내화면의 다음/계속류의 버튼에서 현재 권한상태 체크하고 권한요구 팝업 표시 또는 다음 진행
  2. 권한사진 선택 시스템피커를 .fullScreen으로 표시

앗 난 2번이 맘에 드는데... 시스템이 띄우는건데 어떻게 띄우지? 이케저케요케 테스트 해보니 안내화면 VC에서 아래 함수를 오버라이해서 .fullScreen으로 띄울 수 있었다. (viewControllerToPresent이 타입체크 등이 필요할 수도)

override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
		viewControllerToPresent.modalPresentationStyle = .fullScreen
		super.present(viewControllerToPresent, animated: flag, completion: completion)
	}

아니 애플아 handler는 호출해줘야지?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment