Skip to content

Conversation

@hsw1920
Copy link
Collaborator

@hsw1920 hsw1920 commented Nov 27, 2024

🤔 배경

사진을 저장하거나 공유하는 기능을 구현하면서, 사진 라이브러리 접근 권한 요청 및 사진 저장 관련 로직이 필요했습니다.
이에 따라, 권한 요청과 사진 저장 기능을 관리하는 구조를 설계해야 했습니다.
다른 피쳐와 마찬가지로 권한 및 사진 저장 담당을 in/out 패턴으로 구현 및 리팩터링 했습니다.

📃 작업 내역

사진 접근 권한 관련

  • Info.plist에 사진 접근 권한 키를 추가했습니다.
image

유틸리티 추가

  • 사진 권한, 앨범에 사진 저장을 위해 PhotoLibraryPermissionManagerPhotoLibraryHelper를 구현했습니다.

UI 구현

  • 권한 접근 관련 Alert UI를 구현했습니다.
  • 저장 성공 시 유저 인터랙션을 위한 토스트 UI를 활용했습니다.

✅ 리뷰 노트

권한 관련

    static func checkPhotoPermission() async -> Bool {
        let status = PHPhotoLibrary.authorizationStatus()
        print(status)
        switch status {
        case .notDetermined:
            return await requestAuthorization()
        case .authorized, .limited:
            return true
        case .denied, .restricted:
            return false
        @unknown default:
            return false
        }
    }
  • .notDetermined: 사진 접근 권한을 부여하지 않은 상태입니다. requestAuthorization()로 권한 요청을 진행합니다.
  • .authorized, .limited: 사진 접근 권한이 허용되거나 일부 제한된 상태로 권한이 충분하므로 사진 저장을 할 수 있습니다.
  • .denied, .restricted: 사용자가 명시적으로 접근을 거부하거나 / 시스템 정책에 따라 접근이 제한된 상태이므로 권한 설정을 유도하는 알러트를 두었습니다.

비동기 로직 구현

  • 권한 요청 및 사진 저장에서 비동기 로직이 사용되어야 했습니다.
  • async/await를 활용하여 비동기 처리를 단순화했습니다.
  • escaping 콜백 기반의 코드보다 가독성이 좋아 활용해보았습니다.
func transform(input: AnyPublisher<Input, Never>) -> AnyPublisher<Output, Never> {
    input.sink { [weak self] event in
        switch event {
        case .shareButtonDidTap:
            self?.output.send(.showShareSheet)
        case .saveButtonDidTap:
            Task { await self?.handleSaveButtonDidTap() }
        }
    }
    .store(in: &cancellables)
    
    return output.eraseToAnyPublisher()
}

private func handleSaveButtonDidTap() async {
    guard await isAuthorized() else {
        output.send(.showAuthorizationAlert)
        return
    }
    
    let isSuccess = await savePhoto()
    output.send(isSuccess ? .showSaveToast : .showFailToast)
}

private func savePhoto() async -> Bool {
    return await PhotoLibraryHelper.savePhoto(with: photoData)
}

private func isAuthorized() async -> Bool {
    return await PhotoLibraryPermissionManager.checkPhotoPermission()
}

🎨 스크린샷

.notDetermined .authorized, .limited .denied, .restricted
권한 토스트 일부 접근

🚀 테스트 방법

SharePhotoFeatureDemo를 실행하고 저장, 공유 버튼 기능을 테스트해볼 수 있습니다.

@hsw1920 hsw1920 added ✨ feat 새로운 기능 추가 ⚙️ refactor 코드 정상화 labels Nov 27, 2024
@hsw1920 hsw1920 self-assigned this Nov 27, 2024
@hsw1920 hsw1920 linked an issue Nov 27, 2024 that may be closed by this pull request
2 tasks
@hsw1920 hsw1920 requested review from 0Hooni, Kiyoung-Kim-57 and youn9k and removed request for 0Hooni and Kiyoung-Kim-57 November 27, 2024 16:25
@0Hooni 0Hooni linked an issue Nov 28, 2024 that may be closed by this pull request
2 tasks
Copy link
Collaborator

@0Hooni 0Hooni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Copy link
Member

@youn9k youn9k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link
Member

@Kiyoung-Kim-57 Kiyoung-Kim-57 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hsw1920 hsw1920 merged commit 3e6f1d0 into develop Nov 30, 2024
1 check passed
@hsw1920 hsw1920 deleted the feat/#118-save-share-photo branch November 30, 2024 05:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 새로운 기능 추가 ⚙️ refactor 코드 정상화

Projects

None yet

Development

Successfully merging this pull request may close these issues.

저장버튼을 눌러 이미지를 저장한다 사진 권한을 얻는다

5 participants