다음과 같은 시스템 권한 얼럿을 RxSwift를 이용하여 띄워보자!
PermissionManager 라는 이름을 가진 싱글톤 클래스를 만들어 권한 확인 및 요청 관련 메서드를 관리
public final class PermissionManager {
public static let shared = PermissionManager()
private init() { }
private let disposeBag = DisposeBag()
...
}
권한 요청
RxSwift를 사용하여 구현하려고 하기 때문에 Observable 타입을 리턴하도록 구현
리턴되는 Bool타입의 데이터는 해당 권한을 허용했는지 여부이다.
알림 권한 요청
알림 권한 얼럿의 메세지는 시스템 내부에 정해져있다.
알림에 대한 얼럿과 소리 뱃지 등의 옵션만 설정하면 얼럿 메세지가 만들어진다!
func requestNotificationPermission() -> Observable<Bool> {
return Observable<Bool>.create { observable in
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) { isAllow, _ in
observable.onNext(isAllow)
observable.onCompleted()
}
return Disposables.create()
}
}
사용 예시
특정 버튼을 탭했을 때 권한 요청
button.rx.tap
.flatMap {
PermissionManager().checkPermission(for: .camera)
}
.subscribe(with: self) { owner, status in
// 권한 상태에 따라 적절한 액션 구현
}
.disposed(by: disposBag())
카메라, 앨범 권한 요청
info.plist에서 권한 메세지 설정이 필요
privacy - NSCameraUsageDescription
privacy - Photo Library Description
import AVFoundation
import Photos
// ...
func requestCameraPermission() -> Observable<Bool> {
Observable<Bool>.create { observable in
AVCaptureDevice.requestAccess(for: .video) { granted in
observable.onNext(granted)
observable.onCompleted()
}
return Disposables.create()
}
}
func requestPhotoPermission() -> Observable<Bool> {
Observable<Bool>.create { observable in
PHPhotoLibrary.requestAuthorization(for: .addOnly) { state in
if state == .authorized {
observable.onNext(true)
observable.onCompleted()
} else {
observable.onNext(false)
observable.onCompleted()
}
}
return Disposables.create()
}
}
모든 권한 한 번에 요청하기
앱을 처음 진입했다면 처음에 필요한 권한을 모두 요청받는게 필요할 수 있다.
필요한 권한을 하나씩 요청하는 메서드를 구현해보자
func requestAllPermission() -> Observable<Void> {
return requestNotificationPermission()
.map { _ in Void() }
.flatMap { _ in
self.requestCameraPermission()
.map { _ in Void()}
}
.flatMap {
self.requestPhotoPermission()
.map { _ in Void() }
}
}
알림-카메라-앨범 순서로 권한 요청 얼럿을 띄울 수 있다.
권한 상태 확인
.notDetermined: 권한 요청 받은 적 없음을 의미
해당 경우라면 위에서 구현한 권한 요청 메서드를 호출하여 허용 여부를 불러올 수 있다.
알림권한
// 알림 권한
var notificationPermission: Observable<Bool> {
return Observable<Bool>.create { observable in
UNUserNotificationCenter.current().getNotificationSettings { settings in
switch settings.authorizationStatus {
case .notDetermined:
self.requestNotificationPermission()
.subscribe(onNext: { isAllowed in
observable.onNext(isAllowed)
observable.onCompleted()
})
.disposed(by: self.disposeBag)
case .authorized:
observable.onNext(true)
observable.onCompleted()
default:
observable.onNext(false)
observable.onCompleted()
}
}
return Disposables.create()
}
}
카메라 권한
var cameraPermission: Observable<Bool> {
return Observable<Bool>.create { observable in
let status = AVCaptureDevice.authorizationStatus(for: .video)
switch status {
case .notDetermined:
self.requestCameraPermission()
.subscribe { isAllowed in
observable.onNext(isAllowed)
observable.onCompleted()
}
.disposed(by: self.disposeBag)
case .authorized:
observable.onNext(true)
observable.onCompleted()
default:
observable.onNext(false)
observable.onCompleted()
}
return Disposables.create()
}
}
앨범 권한
// 앨범 권한
var photoPermission: Observable<Bool> {
return Observable<Bool>.create { observable in
let status = PHPhotoLibrary.authorizationStatus(for: .addOnly)
switch status {
case .notDetermined:
self.requestPhotoPermission()
.subscribe { isAllowed in
observable.onNext(isAllowed)
observable.onCompleted()
}
.disposed(by: self.disposeBag)
case .authorized:
observable.onNext(true)
observable.onCompleted()
default:
observable.onNext(false)
observable.onCompleted()
}
return Disposables.create()
}
}
권한 상태 확인을 보다 깔끔하게 사용하기
각각의 다른 프로퍼티를 호출하여 사용하는 것 보다 하나의 메서드를 사용하는게 더 간단하고 가독성이 좋을 것 같다.
권한 타입 정의
enum PermissionType {
case notification, camera, photo
}
권한 확인 메서드 구현
파라미터로 확인하고자 하는 권한 타입을 넣어 확인할 수 있다!
func checkPermission(for type: PermissionType) -> Observable<Bool> {
switch type {
case .notification:
return notificationPermission
case .camera:
return cameraPermission
case .photo:
return photoPermission
}
}
사용 예시
button.rx.tap
.flatMap {
PermissionManager().checkPermission(for: .camera)
}
.subscribe(with: self) { owner, status in
...
}
.disposed(by: disposBag)
'iOS > 🗂️ 내 코드 기록하기' 카테고리의 다른 글
[iOS/Swift] 인앱에서 앱스토어 리뷰 팝업 띄우기 (0) | 2024.10.24 |
---|---|
[iOS/SwiftUI] Text 더보기 버튼 만들기 - ViewThatFits (1) | 2024.04.19 |
[iOS/Swift] 토글되는 컬렉션뷰 만들기 - NSDiffableDataSourceSectionSnapshot (0) | 2024.02.22 |