[SWIFT] PH Authorization Status for iOS 14 or later

Introduction

On iOS, you need to properly request permissions from the user in order to access the camera roll. With iOS14, PHAccessLevel and PHAuthorizationStatus.limited have been added, and the behavior has become complicated, so this is a memorandum of investigation. This is a summary of PHAuthorizationStatus according to the status of "Allow access to photos" and what you can do.

For iOS 13 or lower

Confirmation: iOS 13.4.1

"Allow access to photos" authorizationStatus() requestAuthorization()
unconfirmed .notDetermined ○ (displayed)
reading/writing .authorized × (not displayed)
not allowed .denied ×

For iOS 14 or later

Confirmation: iOS 14.2.1

unconfirmed

"Allow access to photos" authorizationStatus() authorizationStatus
(for: .addOnly)
authorizationStatus
(for: .readWrite)
requestAuthorization
(for: .addOnly)
requestAuthorization
(for: .readWrite)
unconfirmed .notDetermined .notDetermined .notDetermined

Check only requestAuthorization (for: .addOnly)

"Allow access to photos" authorizationStatus() authorizationStatus
(for: .addOnly)
authorizationStatus
(for: .readWrite)
requestAuthorization
(for: .addOnly)
requestAuthorization
(for: .readWrite)
Add photo only
(requestAuthorization(for: .addOnly)"OK")
.notDetermined .authorized .notDetermined ×
None
(requestAuthorization(for: .addOnly)"Do not allow")
.notDetermined .denied .notDetermined ×

Check only requestAuthorization (for: .readWrite)

"Allow access to photos" authorizationStatus() authorizationStatus
(for: .addOnly)
authorizationStatus
(for: .readWrite)
requestAuthorization
(for: .addOnly)
requestAuthorization
(for: .readWrite)
Selected photo
(requestAuthorization(for: .readWrite)で「Selected photo」)
.authorized .limited .limited × ×
All photos
(requestAuthorization(for: .readWrite)"Allow access to all photos")
.authorized .authorized .authorized × ×
None
(requestAuthorization(for: .readWrite)"Do not allow")
.denied .notDetermined .denied ×

Check both requestAuthorization (for: .addOnly) and requestAuthorization (for: .readWrite)

"Allow access to photos" authorizationStatus() authorizationStatus
(for: .addOnly)
authorizationStatus
(for: .readWrite)
Add photo only .denied .authorized .denied
Selected photo .authorized . limited . limited
All photos .authorized .authorized .authorized
None .denied .denied .denied

Save photos to album as much as possible on iOS 14 or later

Thing you want to do

  1. If you can specify an album and save it, specify an album and save it.
  2. If you cannot specify an album and save it, save it to the camera roll.
  3. If you can't save the image to the camera roll, do nothing

If you can specify an album and save it, specify an album and save it.

Can be saved when ReadWrite AuthorizationStatus is .authorized

PHPhotoLibrary.authorizationStatus(for: .readWrite) == .authorized

If you cannot specify an album and save it, save it to the camera roll.

Can be saved when the authorizationStatus of addOnly is .authorized or .limited

PHPhotoLibrary.authorizationStatus(for: . addOnly) == .authorized or . limited

Judgment device

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)
        }
    }
}

How to use

AuthorizationStatusChecker.checkPhotoLibrary { [weak self](status) in
    switch status {
    case .readWrite:
        self?.saveToAlbum(name: "MyAlbum")
    case .addOnly:
        self?.saveToCameraRoll()
    case .denied:
        break
    }
}

Recommended Posts

PH Authorization Status for iOS 14 or later
Tracking Authorization Status memo on iOS 14