はじめに
iOSでは、カメラロールにアクセスするためには、ユーザに対して適切に権限をリクエストする必要があります。
iOS14になり、PHAccessLevel や PHAuthorizationStatus.limited が追加され、挙動が複雑になったので、調べたことの備忘録です。
「写真のアクセスを許可」の状態に応じた PHAuthorizationStatus と、できることのまとめです。
iOS13以下の場合
- 確認したOSバージョン: iOS13.4.1
「写真のアクセスを許可」 | authorizationStatus() | requestAuthorization() |
---|---|---|
未確認(初期状態) | .notDetermined | ○ (表示される) |
読み出し/書き込み | .authorized | × (表示されない) |
許可しない | .denied | × |
- とてもシンプルです
iOS14以降の場合
確認したOSバージョン: iOS14.2.1
未確認(初期)の状態
「写真のアクセスを許可」 | authorizationStatus() | authorizationStatus (for: .addOnly) |
authorizationStatus (for: .readWrite) |
requestAuthorization (for: .addOnly) |
requestAuthorization (for: .readWrite) |
---|---|---|---|---|---|
未確認 | .notDetermined | .notDetermined | .notDetermined | ○ | ○ |
requestAuthorization(for: .addOnly) のみ確認
- 設定画面の状態
- authorizationStatusの結果
|「写真のアクセスを許可」 |authorizationStatus() |authorizationStatus
(for: .addOnly) |authorizationStatus
(for: .readWrite) |requestAuthorization
(for: .addOnly) |requestAuthorization
(for: .readWrite) |
|---|:-:|:-:|:-:|:-:|:-:|:-:|
|写真の追加のみ
(requestAuthorization(for: .addOnly)で「OK」) |.notDetermined |.authorized |.notDetermined |× |○ |
|なし
(requestAuthorization(for: .addOnly)で「許可しない」) |.notDetermined |.denied |.notDetermined |× |○ |
requestAuthorization(for: .readWrite) のみ確認
- 設定画面の状態
- authorizationStatusの結果
「写真のアクセスを許可」 | authorizationStatus() | authorizationStatus (for: .addOnly) |
authorizationStatus (for: .readWrite) |
requestAuthorization (for: .addOnly) |
requestAuthorization (for: .readWrite) |
---|---|---|---|---|---|
選択した写真 (requestAuthorization(for: .readWrite)で「選択した写真」) |
.authorized | .limited | .limited | × | × |
すべての写真 (requestAuthorization(for: .readWrite)で「全ての写真へのアクセスを許可」) |
.authorized | .authorized | .authorized | × | × |
なし (requestAuthorization(for: .readWrite)で「許可しない」) |
.denied | .notDetermined | .denied | ○ | × |
requestAuthorization(for: .addOnly) と requestAuthorization(for: .readWrite) の両方を確認
-
再現手順
authorizationStatus(for: .addOnly) と authorizationStatus(for: .readWrite) のどちらか片方だけが .notDetermined の時に、.notDetermined の方のAccessLevel で requestAuthorization する -
設定画面の状態
- authorizationStatusの結果
「写真のアクセスを許可」 | authorizationStatus() | authorizationStatus (for: .addOnly) |
authorizationStatus (for: .readWrite) |
---|---|---|---|
写真の追加のみ | .denied | .authorized | .denied |
選択した写真 | .authorized | . limited | . limited |
すべての写真 | .authorized | .authorized | .authorized |
なし | .denied | .denied | .denied |
iOS14以降にできるだけアルバムに写真を保存する
やりたいこと
- アルバムを指定して保存できる時は、アルバムを指定して保存する
- アルバムを指定して保存できない時は、カメラロールに保存する
- カメラロールにも画像を保存できない時は、何もしない
アルバムを指定して保存できる時は、アルバムを指定して保存する
readWrite の AuthorizationStatus が .authorized の時に保存できる
PHPhotoLibrary.authorizationStatus(for: .readWrite) == .authorized
アルバムを指定して保存できない時は、カメラロールに保存する
addOnly の AuthorizationStatus が .authorized もしくは .limited の時に保存できる
PHPhotoLibrary.authorizationStatus(for: . addOnly) == .authorized or . limited
判定器
class AuthorizationStatusChecker {
enum PhotoLibraryAuthorizationStatus {
case readWrite
case addOnly
case denied
}
static func checkPhotoLibrary(handler: @escaping (PhotoLibraryAuthorizationStatus) -> Void) {
let readWrite = PHPhotoLibrary.authorizationStatus(for: .readWrite)
let addOnly = PHPhotoLibrary.authorizationStatus(for: .addOnly)
switch (readWrite, addOnly) {
case (.authorized, _):
handler(.readWrite)
case (.notDetermined, _):
PHPhotoLibrary.requestAuthorization(for: .readWrite) { (_: PHAuthorizationStatus) in
Self.checkPhotoLibrary(handler: handler)
}
case (_, .authorized), (_, .limited):
handler(.addOnly)
case (_, .notDetermined):
PHPhotoLibrary.requestAuthorization(for: .addOnly) { (_: PHAuthorizationStatus) in
Self.checkPhotoLibrary(handler: handler)
}
default:
handler(.denied)
}
}
}
使い方
AuthorizationStatusChecker.checkPhotoLibrary { [weak self] (status) in
switch status {
case .readWrite:
self?.saveToAlbum(name: "MyAlbum")
case .addOnly:
self?.saveToCameraRoll()
case .denied:
break
}
}