각종 퍼미션을 요청해야되는 일이 있어서 일단 사진 / 카메라 퍼미션만 구현했습니다.

다른 퍼미션도 계속 추가해서 동일하게 사용하면 될듯 합니다.

 

[PermissionManager.swift]

import SwiftUI
import Photos

class PermissionManager: ObservableObject {
    @Published var photoPermissionGranted = false
    @Published var cameraPermissionGranted = false
    
    /// 포토라이브러리 권한 체크
    public func requestPhotoLibraryPermission() {
        checkPhotoLibraryPermission { [weak self] (isAuthorize) in
            if isAuthorize == true {
                DispatchQueue.main.async {
                    self?.photoPermissionGranted = true
                }
            }  else {
                self?.requestPermissionSettingAlertAction(mediaType: .photoLibrary)
            }
        }
    }
    
    /// 카메라 사용 권한 체크
    public func requestCameraPermission() {
        checkCameraPermission { [weak self] (isAuthorize) in
            if isAuthorize == true {
                DispatchQueue.main.async {
                    self?.cameraPermissionGranted = true
                }
            }  else {
                self?.requestPermissionSettingAlertAction(mediaType: .camera)
            }
        }
    }
    
    // MARK: 앨범 사용권한 확인
   private func checkPhotoLibraryPermission(complete: @escaping (Bool) -> Void) {
        let status = PHPhotoLibrary.authorizationStatus()
        switch status {
        case .authorized:
            complete(true)
        case .limited:
            complete(true)
        case .denied :
            complete(false)
        case .notDetermined:    // 선택안함.
            requestPhotoLibraryAuthorization { (isAuthorize) in
                complete(isAuthorize)
            }
            
        default: break
        }
    }
    
    /// 앨범 사용권한 요청
    private func requestPhotoLibraryAuthorization(complete: @escaping (Bool) -> Void ) {
        
        DispatchQueue.main.async {
//            PHPhotoLibrary.requestAuthorization(for: .readWrite) { (status) in
            PHPhotoLibrary.requestAuthorization { (status) in
                switch status{
                case .authorized:
                    complete(true)
                case .limited:
                    complete(true)
                case .denied:
                    complete(false)
                case .restricted:
                    complete(false)
                default:
                    complete(false)
                }
            }
        }
    }
    
    // MARK: 카메라 사용권한 확인
    private func checkCameraPermission(complete: @escaping (Bool) -> Void) {
        let status = AVCaptureDevice.authorizationStatus(for: .video)
        switch status {
        case .authorized:
            complete(true)
        case .denied :
            complete(false)
        case .notDetermined:    // 선택안함.
            requestCameraAuthorization { (isAuthorize) in
                complete(isAuthorize)
            }
            
        default: break
        }
    }
    
    /// 카메라 사용권한 요청
    private func requestCameraAuthorization(completion: @escaping (Bool) -> Void ) {
        DispatchQueue.main.async {
            if AVCaptureDevice.authorizationStatus(for: .video) == .authorized{
                completion(true)
            }else{
                AVCaptureDevice.requestAccess(for: .video) { (granted) in
                    completion(granted)
                }
            }
        }
    }
    
    // MARK: 접근권한 설정 알림(권한설정 거부시)
    /// 접근권한 거부시 알림 얼럿 (설정 페이지 이동)
    private func requestPermissionSettingAlertAction(mediaType: UIImagePickerController.SourceType) {
        
        let alertController = UIAlertController(
            title: mediaType == .photoLibrary ? "현재 앨범 사용에 대한 접근 권한이 없습니다." : "현재 카메라 사용에 대한 접근 권한이 없습니다.",
            message: mediaType == .photoLibrary ? "앨범의 사진을 사용하려면 사진 권한이 필요합니다. 권한 설정 화면으로 이동 하시겠습니까?" : "카메라를 사용하려면 권한이 필요합니다. 권한 설정 화면으로 이동 하시겠습니까?",
            preferredStyle: .alert
        )
        let cancelAlert = UIAlertAction(
            title: "취소",
            style: .cancel
        ) { _ in
            alertController.dismiss(animated: true, completion: nil)
        }
        let goToSettingAlert = UIAlertAction(
            title: "설정으로 이동하기",
            style: .default) { _ in
                appSettingOpen()
            }
        [cancelAlert, goToSettingAlert]
            .forEach(alertController.addAction(_:))
        
        guard let topVC = UIApplication.currentTopViewController() else {
            return
        }
        DispatchQueue.main.async {
            topVC.present(alertController, animated: true) // must be used from main thread only
        }
    }
}

 

 

[사용방법]

struct ContentView: View {
	@StateObject var permissionManager = PermissionManager()
    @State var isShowPhotoGridView: Bool = false
    
	var body: some View {
    	VStack {
        	 Button {
 			      permissionManager.requestPhotoLibraryPermission()
 			 } label: {
 			     HStack {
 			         Image(systemName: "globe")
 			         Text("카메라 이미지 촬영")
 			     }
 			 }
 			 .onReceive(imagePickerManager.$photoPermissionGranted, perform: { granted in
             	// 퍼미션 상태 확인
 			     if granted {
 			         isShowPhotoGridView.toggle()
 			     }
 			 })
 			 .fullScreenCover(isPresented: $isShowPhotoGridView,
 			                  content: {
				/*
                커스텀한 멀티선택 가능한 겔러리 UI 인데 추후 개제 하겠습니다. 양이 많아서...
                */
 			     PhotoGridView()
 			 })
        }
    }
}

+ Recent posts