Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
5
Help us understand the problem. What is going on with this article?
@fuziki

iOS14以降のPHAuthorizationStatus

はじめに

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以降にできるだけアルバムに写真を保存する

やりたいこと

  1. アルバムを指定して保存できる時は、アルバムを指定して保存する
  2. アルバムを指定して保存できない時は、カメラロールに保存する
  3. カメラロールにも画像を保存できない時は、何もしない

アルバムを指定して保存できる時は、アルバムを指定して保存する

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
    }
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
5
Help us understand the problem. What is going on with this article?