開発中のアプリでカメラと写真の許可状態を取得しつつ、その状態に合わせてPickerを表示するor許可してくださいの画面を出し分けるというのをRxで組みたかったので小さいextensionを書いた。
写真の許可状態を取得する
extension Reactive where Base: PHPhotoLibrary {
static func requestAuthorization() -> Single<PHAuthorizationStatus> {
return .create { observer in
let status = Base.authorizationStatus()
switch status {
case .notDetermined:
PHPhotoLibrary.requestAuthorization { status in
DispatchQueue.main.async {
observer(.success(status))
}
}
default:
observer(.success(status))
}
return Disposables.create()
}
}
}
カメラの許可状態を取得する
extension Reactive where Base: AVCaptureDevice {
static func requestAuthorization(for mediaType: AVMediaType) -> Single<AVAuthorizationStatus> {
return .create { observer in
let status = Base.authorizationStatus(for: mediaType)
switch status {
case .notDetermined:
AVCaptureDevice.requestAccess(for: mediaType) { authorized in
DispatchQueue.main.async {
observer(.success(authorized ? .authorized : .denied))
}
}
default:
observer(.success(status))
}
return Disposables.create()
}
}
}
いずれも事前にstatusが取れるので、取得し、notDetermined
ならrequestを行い、ユーザーに許可ダイアログを表示し、その結果を返すようにする。
それ以外の場合はすぐにobserverに値を流し込むようにしている。
利用例
ボタンのイベントなりと組み合わせて、それに応じてPickerを表示したり、許可してねというアラートを出しつつ設定画面に飛ばしたり、を実装している。
albumButton.rx.tap
.flatMap { PHPhotoLibrary.rx.requestAuthorization() }
.map { $0 == .authorized }
.bind { authorized in
if authorized {
// pickerを表示
} else {
// アクセス許可してねというアラートなりを表示
}
}
.disposed(by: disposeBag)