Определите, установлен ли доступ к библиотеке фотографий или нет - PHPhotoLibrary

Благодаря новой функциональности в iOS 8, если вы используете камеру в приложении, она запросит разрешение на доступ к камере, а затем, когда вы попытаетесь повторно сделать снимок, он запросит разрешение на доступ к библиотеке фотографий. В следующий раз, когда я запускаю приложение, я хочу проверить, есть ли у камеры и библиотеки фотографий права доступа к нему.

введите описание изображения здесь

Для камеры проверяю по

if ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] == AVAuthorizationStatusDenied)
{
// do something
}

Я ищу нечто подобное для библиотеки фотографий.


person tech_human    schedule 27.10.2014    source источник


Ответы (10)


Отметьте +[PHPhotoLibrary authorizationStatus] - если не установлено, вернет PHAuthorizationStatusNotDetermined. (Затем вы можете запросить доступ, используя +requestAuthorization: в том же классе.)

person Tim    schedule 27.10.2014
comment
Нужно ли мне добавлять / импортировать какой-либо фундамент или библиотеку для использования PHPhotoLibrary? Я получаю сообщение об ошибке Использование необъявленного идентификатора - person tech_human; 27.10.2014
comment
Я попытался использовать ALAssetsLibrary вместо этого, чтобы проверить статус авторизации, и он вернул ДА, даже если библиотека фотографий отключена. - person tech_human; 27.10.2014
comment
О, я могу получить статус с помощью ALAssetsLibrary. Все еще любопытно узнать, можно ли использовать библиотеку PHPhoto. - person tech_human; 27.10.2014
comment
PHPhotoLibrary является частью платформы Photos, которая доступна только в iOS 8. Если вам нужна поддержка более старых версий iOS, возможно, лучше всего подойдет ALAssetsLibrary. - person Tim; 28.10.2014
comment
Что касается iOS 9, ALAssetsLibrary устарела, поэтому я думаю, поэтому она не работает. - person Supertecnoboff; 07.10.2015
comment
Вам необходимо включить модули (C и Objective-C) в настройках сборки вашего проекта. Это позволит вам использовать (@import Photos;) и объявить свойство PHPhotoLibrary. - person 3rdeye7; 30.12.2015
comment
Есть ли у кого-нибудь из вас проблемы с повторной проверкой этого свойства после того, как оно было изменено в настройках, пока приложение все еще работало (не было убито)? У меня старый статус даже при звонке + запрос авторизации: Кстати. протестировано с iOS 9.3 - person Balki; 24.03.2016
comment
Просто импортируйте PhotosUI Вот и все! - person Anurag Sharma; 16.03.2017
comment
Начиная с iOS 8, мы также должны предоставить описание использования (которое требуется для PHPhotoLibrary). Вот полный ответ: вот решение для iOS 8 и выше: stackoverflow.com/questions/26595343/ - person Just Shadow; 06.05.2017

Я знаю, что на это уже был дан ответ, но просто чтобы расширить ответ @Tim, вот код, который вам нужен (iOS 8 и выше):

PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];

if (status == PHAuthorizationStatusAuthorized) {
     // Access has been granted.
}

else if (status == PHAuthorizationStatusDenied) {
     // Access has been denied.
}

else if (status == PHAuthorizationStatusNotDetermined) {

     // Access has not been determined.
     [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {

         if (status == PHAuthorizationStatusAuthorized) {
             // Access has been granted.         
         }

         else {
             // Access has been denied.
         }
     }];  
}

else if (status == PHAuthorizationStatusRestricted) {
     // Restricted access - normally won't happen.
}

Не забудьте #import <Photos/Photos.h>

Если вы используете Swift 3.0 или выше, вы можете использовать следующий код:

// Get the current authorization state.
let status = PHPhotoLibrary.authorizationStatus()

if (status == PHAuthorizationStatus.authorized) {
    // Access has been granted.
}

else if (status == PHAuthorizationStatus.denied) {
    // Access has been denied.
}

else if (status == PHAuthorizationStatus.notDetermined) {

    // Access has not been determined.
    PHPhotoLibrary.requestAuthorization({ (newStatus) in

        if (newStatus == PHAuthorizationStatus.authorized) {

        }

        else {

        }
    })
}

else if (status == PHAuthorizationStatus.restricted) {
    // Restricted access - normally won't happen.
}

Не забудьте import Photos

person Supertecnoboff    schedule 07.10.2015
comment
Почему это только iOS 9 и выше? Фреймворк для фотографий доступен с iOS 8 .. - person Balázs Vincze; 23.01.2016
comment
Также не забудьте добавить в проект структуру фотографий - ›Цель -› Этапы сборки - person stellz; 05.05.2017
comment
Он не работает должным образом, я отказал в доступе, затем снова включил его, он все еще говорит, что не определен. - person TomSawyer; 21.09.2017
comment
// Ограниченный доступ - обычно не бывает. Почему? Это могло произойти: пользователь не может изменить статус этого приложения, возможно, из-за активных ограничений. - person NoKey; 06.02.2018
comment
предполагает ли PHPhotoLibrary.requestAuthorization показывать диалоговое окно с запросом разрешения? Потому что правильный вызов этой линии ничего не делает - person iori24; 06.08.2018
comment
Я бы предпочел использовать подход с переключателем, а не if else - person Bogdan Laukhin; 03.07.2019

В качестве формальности, версия Swift 2.X:

    func checkPhotoLibraryPermission() {
       let status = PHPhotoLibrary.authorizationStatus()
       switch status {
       case .Authorized:
            //handle authorized status
       case .Denied, .Restricted :
            //handle denied status
       case .NotDetermined:
            // ask for permissions
            PHPhotoLibrary.requestAuthorization() { (status) -> Void in
               switch status {
               case .Authorized:
                   // as above
               case .Denied, .Restricted:
                   // as above
               case .NotDetermined:
                   // won't happen but still
               }
            }
        }
    }

И Swift 3 / Swift 4:

    import Photos

    func checkPhotoLibraryPermission() {
        let status = PHPhotoLibrary.authorizationStatus()
        switch status {
        case .authorized: 
        //handle authorized status
        case .denied, .restricted : 
        //handle denied status
        case .notDetermined: 
            // ask for permissions
            PHPhotoLibrary.requestAuthorization { status in
                switch status {
                case .authorized: 
                // as above
                case .denied, .restricted: 
                // as above
                case .notDetermined: 
                // won't happen but still
                }
            }
        }
    }
person Krodak    schedule 01.03.2016
comment
В Swift 3 не забудьте import Photos, если вы хотите использовать PHPhotoLibrary. - person ronatory; 18.10.2016

Вот полное руководство для iOS 8+ (без ALAssetLibrary):

Во-первых, мы должны предоставить описание использования как сейчас. это требуется для PHPhotoLibrary.
Для этого мы должны открыть файл info.plist, найти ключ Privacy - Photo Library Usage Description и указать для него значение. Если ключа не существует, просто создайте его.
Вот изображение, например:
введите описание изображения здесь Также убедитесь, что значение ключа Bundle name не пусто в info.plist файле.

Теперь, когда у нас есть описание, мы обычно можем запросить авторизацию, вызвав метод requestAuthorization:

[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    switch (status) {
        case PHAuthorizationStatusAuthorized:
            NSLog(@"PHAuthorizationStatusAuthorized");
            break;
        case PHAuthorizationStatusDenied:
            NSLog(@"PHAuthorizationStatusDenied");
            break;
        case PHAuthorizationStatusNotDetermined:
            NSLog(@"PHAuthorizationStatusNotDetermined");
            break;
        case PHAuthorizationStatusRestricted:
            NSLog(@"PHAuthorizationStatusRestricted");
            break;
    }
}];

ПРИМЕЧАНИЕ 1. requestAuthorization фактически не показывает оповещение при каждом звонке. Он отображается один раз в какое-то время, сохраняет ответ пользователя и возвращает его каждый раз вместо того, чтобы снова показывать предупреждение. Но поскольку это не то, что нам нужно, вот полезный код, который всегда показывает предупреждение каждый раз, когда нам нужно разрешение (с перенаправлением на настройки):

- (void)requestAuthorizationWithRedirectionToSettings {
    dispatch_async(dispatch_get_main_queue(), ^{
        PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
        if (status == PHAuthorizationStatusAuthorized)
        {
            //We have permission. Do whatever is needed
        }
        else
        {
            //No permission. Trying to normally request it
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                if (status != PHAuthorizationStatusAuthorized)
                {
                    //User don't give us permission. Showing alert with redirection to settings
                    //Getting description string from info.plist file
                    NSString *accessDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSPhotoLibraryUsageDescription"];
                    UIAlertController * alertController = [UIAlertController alertControllerWithTitle:accessDescription message:@"To give permissions tap on 'Change Settings' button" preferredStyle:UIAlertControllerStyleAlert];
                    
                    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
                    [alertController addAction:cancelAction];
                    
                    UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:@"Change Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
                    }];
                    [alertController addAction:settingsAction];
                    
                    [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
                }
            }];
        }
    });
}

Распространенная проблема 1. Некоторые пользователи жалуются, что приложение не показать предупреждение после внесения вышеупомянутых изменений в файл info.plist.
Решение: для тестирования попробуйте изменить Bundle Identifier из файла проекта на что-то другое, очистите и пересоберите приложение. Если заработало то все нормально, переименуйте обратно.

Распространенная проблема 2. В некоторых случаях результаты выборки не обновляются (и представления, в которых использовались изображения из этих запросов на выборку, по-прежнему остаются пустыми), когда приложение получает разрешения для фотографий, во время работы , как было обещано в документации.
На самом деле это происходит, когда мы используем НЕПРАВИЛЬНЫЙ код, например:

- (void)viewDidLoad {
    if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
    {
        //Reloading some view which needs photos
        [self reloadCollectionView];
        // ...
    } else {
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status == PHAuthorizationStatusAuthorized)
                [self reloadCollectionView];
            // ...
        }];
    }
    // ...
}

В этом случае, если пользователь отказался предоставлять разрешения на viewDidLoad, а затем перешел к настройкам, разрешил и вернулся в приложение, представления не будут обновлены, потому что [self reloadCollectionView] и запросы на выборку не были отправлены.
Решение: нам просто нужно вызовите [self reloadCollectionView] и выполните другие запросы на выборку, прежде чем требовать авторизации, например:

- (void)viewDidLoad {
    //Reloading some view which needs photos
    [self reloadCollectionView];
    if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
    {
        // ...
}
person Just Shadow    schedule 15.07.2016
comment
Как связать настройки приложения с разрешениями? - person user2924482; 17.05.2017

У меня так получилось:

- (void)requestPermissions:(GalleryPermissions)block
{
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];

    switch (status) 
    {
        case PHAuthorizationStatusAuthorized:
            block(YES);
            break;
        case PHAuthorizationStatusNotDetermined:
        {
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus authorizationStatus)
            {
                if (authorizationStatus == PHAuthorizationStatusAuthorized)
                {
                    block(YES);
                }
                else
                {
                    block(NO);
                }
            }];
            break;
        }
        default:
            block(NO);
            break;
    }
}

И я отправляю то, что мне нужно сделать, в качестве блока в зависимости от успеха или неудачи.

person Shades    schedule 25.08.2015

iOS 14 и более поздние версии Apple добавила новую функцию, которая предоставит ограниченный доступ к библиотеке фотографий. В зависимости от ваших требований (пример создания настраиваемой фотогалереи) вы должны проверить, предоставил ли пользователь только ограниченный доступ и хочет ли предоставить полный доступ.

Для обратной совместимости старые версии без параметра возвращают .authorized даже при ограниченном доступе.

Swift 5:

switch PHPhotoLibrary.authorizationStatus(for: .readWrite) {
case .notDetermined:
    // ask for access
case .restricted, .denied:
    // sorry
case .authorized:
    // we have full access
 
// new option: 
case .limited:
    // we only got access to some photos of library
}

Есть код для повторного вызова экрана ограниченного доступа. если пользователь предоставил только .ограниченный доступ, и вы хотите, чтобы пользователь снова выбирал изображения.

PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: presentVCObj)

При каждом перезапуске приложения iOS будет показывать предупреждение, чтобы уведомить пользователя об ограниченном доступе. Если вы хотите отключить это оповещение, добавьте PHPhotoLibraryPreventAutomaticLimitedAccessAlert к ДА в Info.plist.

person user1039695    schedule 27.08.2020
comment
Это решение не работает. Для PHPhotoLibraryPreventAutomaticLimitedAccessAlert установлено значение YES. Нужно ли делать какие-либо другие настройки после добавления этого ключа в info.plist? - person Hardik Thakkar; 08.10.2020

ОБНОВЛЕНИЕ для: SWIFT 3 IOS10


Примечание: импортируйте фотографии в AppDelegate.swift следующим образом

// AppDelegate.swift

импортировать UIKit

импортировать фотографии

...


func applicationDidBecomeActive(_ application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    photoLibraryAvailabilityCheck()

}

//MARK:- PHOTO LIBRARY ACCESS CHECK
func photoLibraryAvailabilityCheck()
{
    if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized
    {

    }
    else
    {
        PHPhotoLibrary.requestAuthorization(requestAuthorizationHandler)
    }
}
func requestAuthorizationHandler(status: PHAuthorizationStatus)
{
    if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized
    {

    }
    else
    {
        alertToEncouragePhotoLibraryAccessWhenApplicationStarts()
    }
}

//MARK:- CAMERA & GALLERY NOT ALLOWING ACCESS - ALERT
func alertToEncourageCameraAccessWhenApplicationStarts()
{
    //Camera not available - Alert
    let internetUnavailableAlertController = UIAlertController (title: "Camera Unavailable", message: "Please check to see if it is disconnected or in use by another application", preferredStyle: .alert)

    let settingsAction = UIAlertAction(title: "Settings", style: .destructive) { (_) -> Void in
        let settingsUrl = NSURL(string:UIApplicationOpenSettingsURLString)
        if let url = settingsUrl {
            DispatchQueue.main.async {
                UIApplication.shared.open(url as URL, options: [:], completionHandler: nil) //(url as URL)
            }

        }
    }
    let cancelAction = UIAlertAction(title: "Okay", style: .default, handler: nil)
    internetUnavailableAlertController .addAction(settingsAction)
    internetUnavailableAlertController .addAction(cancelAction)
    self.window?.rootViewController!.present(internetUnavailableAlertController , animated: true, completion: nil)
}
func alertToEncouragePhotoLibraryAccessWhenApplicationStarts()
{
    //Photo Library not available - Alert
    let cameraUnavailableAlertController = UIAlertController (title: "Photo Library Unavailable", message: "Please check to see if device settings doesn't allow photo library access", preferredStyle: .alert)

    let settingsAction = UIAlertAction(title: "Settings", style: .destructive) { (_) -> Void in
        let settingsUrl = NSURL(string:UIApplicationOpenSettingsURLString)
        if let url = settingsUrl {
            UIApplication.shared.open(url as URL, options: [:], completionHandler: nil)
        }
    }
    let cancelAction = UIAlertAction(title: "Okay", style: .default, handler: nil)
    cameraUnavailableAlertController .addAction(settingsAction)
    cameraUnavailableAlertController .addAction(cancelAction)
    self.window?.rootViewController!.present(cameraUnavailableAlertController , animated: true, completion: nil)
}

Ответ обновлен от Элвина Джорджа

person MLBDG    schedule 15.11.2016

Использование ALAssetsLibrary должно работать:

ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
switch (status) {
    case ALAuthorizationStatusNotDetermined: {
        // not determined
        break;
    }
    case ALAuthorizationStatusRestricted: {
        // restricted
        break;
    }
    case ALAuthorizationStatusDenied: {
        // denied
        break;
    }
    case ALAuthorizationStatusAuthorized: {
        // authorized
        break;
    }
    default: {
        break;
    }
}
person richy    schedule 10.06.2015
comment
Отличный ответ, но это устарело в iOS 9. - person Supertecnoboff; 07.10.2015

Вот небольшой и простой фрагмент, который я обычно использую.

- (void)requestPhotoAuthorization:(void (^)(BOOL granted))granted
{
    void (^handler)(PHAuthorizationStatus) = ^(PHAuthorizationStatus status)
    {
        if (status == PHAuthorizationStatusAuthorized) granted(YES);
        else if (status == PHAuthorizationStatusNotDetermined) [PHPhotoLibrary requestAuthorization:handler];
        else granted(NO);
    };
    handler([PHPhotoLibrary authorizationStatus]);
}
person Camo    schedule 19.08.2015
comment
Кажется, что он не возвращает предоставленный (ДА) или предоставленный (НЕТ), если он не определен? - person Shades; 25.08.2015
comment
как указано выше + сильный захват 'обработчика' в этом блоке, вероятно, приведет к циклу сохранения - person Ernest; 14.09.2019

Swift 2.0+

Основываясь на комбинации ответов здесь, я создал решение для себя. Этот метод проверяет только отсутствие разрешения.

У нас есть метод pickVideo(), требующий доступа к фотографиям. Если это не .Authorized, спросите разрешения.

Если разрешение не предоставлено, pickVideo() не будет вызываться, и пользователь не сможет выбрать видео.

Пока пользователь не предоставил полный доступ к фотографиям, вы можете не позволять ему выбирать или «вылетать» из вашего приложения.

  // Method that requires access to photos
  func pickVideo(){
    // Check for permission
    if PHPhotoLibrary.authorizationStatus() != .Authorized{
      // If there is no permission for photos, ask for it
      PHPhotoLibrary.requestAuthorization(requestAuthorizationHandler)
      return
    }
    //... pick video code here...
  }

  func requestAuthorizationHandler(status: PHAuthorizationStatus){
    if PHPhotoLibrary.authorizationStatus() == .Authorized{
      // The user did authorize, so, pickVideo may be opened
      // Ensure pickVideo is called from the main thread to avoid GUI problems
      dispatch_async(dispatch_get_main_queue()) {
        pickVideo()
      }
    } else {
      // Show Message to give permission in Settings
      let alertController = UIAlertController(title: "Error", message: "Enable photo permissions in settings", preferredStyle: .Alert)
      let settingsAction = UIAlertAction(title: "Settings", style: .Default) { (alertAction) in
        if let appSettings = NSURL(string: UIApplicationOpenSettingsURLString) {
          UIApplication.sharedApplication().openURL(appSettings)
        }
      }
      alertController.addAction(settingsAction)
      // If user cancels, do nothing, next time Pick Video is called, they will be asked again to give permission
      let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
      alertController.addAction(cancelAction)
      // Run GUI stuff on main thread
        dispatch_async(dispatch_get_main_queue()) {      
          self.presentViewController(alertController, animated: true, completion: nil)
        }
      }
    }
person Gerrit Post    schedule 01.04.2016