Determinar si el acceso a la biblioteca de fotos está configurado o no – PHPhotoLibrary

Con la nueva funcionalidad en iOS 8, si está usando una cámara en la aplicación, le pedirá permiso para acceder a la cámara y luego cuando intente volver a tomar la foto, le pedirá permiso para acceder a la biblioteca de fotos. La próxima vez que lance la aplicación, deseo verificar si la cámara y la biblioteca de fotos tienen permisos de acceso a ella.

enter image description here

Para la cámara, lo controlo por

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

Estoy buscando algo similar a esto para la biblioteca de fotos.

Check +[PHPhotoLibrary authorizationStatus] – si no está configurado, devolverá PHAuthorizationStatusNotDetermined . (Luego puede solicitar el acceso usando +requestAuthorization: en la misma clase).

Sé que esto ya ha sido respondido, pero solo para expandir la respuesta de @Tim, aquí está el código que necesitas (iOS 8 y superior):

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

No te olvides de #import

Si está utilizando Swift 3.0 o superior, puede usar el siguiente código:

 // 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. } 

No te olvides de import Photos

Al igual que la formalidad, la versión de 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 } } } } 

Y Swift 3 :

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

Aquí hay una guía completa para iOS 8 y superior (sin ALAssetLibrary):

En primer lugar, debemos proporcionar una descripción de uso tal como lo requiere PHPhotoLibrary.
Para hacer esto, debemos abrir el archivo info.plist , encontrar la clave Privacy - Photo Library Usage Description y brindarle un valor. Si la clave no existe, solo créela.
Aquí hay una imagen, por ejemplo:
enter image description here También asegúrese de que el valor del Bundle name clave no esté vacío en el archivo info.plist .

Ahora cuando tenemos la descripción, normalmente podemos solicitar autorización llamando requestAuthorization método 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; } }]; 

NOTA 1: requestAuthorization realmente no muestra alerta en cada llamada. Se muestra una vez cada cierto tiempo, guarda la respuesta del usuario y la devuelve cada vez en lugar de mostrar la alerta nuevamente. Pero como no es lo que necesitamos, aquí hay un código útil que siempre muestra alerta cada vez que necesitamos permiso (con la redirección a la configuración):

 - (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]; } }]; } }); } 

Problema común 1: algunos usuarios se quejan de que la aplicación no muestra alerta después de realizar los cambios mencionados anteriormente en el archivo info.plist .
Solución: Para probar intente cambiar el Bundle Identifier del archivo de proyecto a otra cosa, limpie y vuelva a generar la aplicación. Si comenzó a funcionar, entonces todo está bien, renómbrelo de nuevo.

Problema común 2: hay un caso específico en el que los resultados de búsqueda no se actualizan (y las vistas que utilizan imágenes de esas solicitudes de búsqueda aún se vacían en consecuencia) cuando la aplicación obtiene permisos para las fotos, mientras se ejecuta como se prometió en la documentación.
En realidad sucede cuando usamos un código INCORRECTO como este:

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

En este caso, si el usuario denegó la concesión de permisos en viewDidLoad luego saltó a la configuración, permitió y saltó a la aplicación, las vistas no se actualizarán porque no se enviaron [self reloadCollectionView] y las solicitudes de búsqueda.
Solución: solo tenemos que llamar a [self reloadCollectionView] y hacer otras solicitudes de recuperación antes de solicitar una autorización como esta:

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

Lo hice así:

 - (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; } } 

Y envío lo que tengo que hacer como bloque dependiendo del éxito o el fracaso.

ACTUALIZACIÓN para: SWIFT 3 IOS10


Nota: importe fotos en AppDelegate.swift de la siguiente manera

// AppDelegate.swift

importar UIKit

importar fotos


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

Respuesta actualizada de Alvin George

Usar ALAssetsLibrary debería funcionar:

 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; } } 
 I have a simple solution on swift 2.0 // // AppDelegate.swift // HoneyBadger // // Created by fingent on 14/08/15. // Copyright (c) 2015 fingent. All rights reserved. // import UIKit import Photos @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { self.window?.makeKeyAndVisible() self.window = UIWindow(frame: UIScreen.mainScreen().bounds) let storyboard = UIStoryboard(name: "Main", bundle: nil) let initialViewController = storyboard.instantiateViewControllerWithIdentifier("LoginPageID") self.window?.rootViewController = initialViewController self.window?.makeKeyAndVisible() return true } func applicationDidEnterBackground(application: UIApplication) { print("Application On background", terminator: "") } func applicationDidBecomeActive(application: UIApplication) { cameraAllowsAccessToApplicationCheck() photoLibraryAvailabilityCheck() } //MARK:- CAMERA ACCESS CHECK func cameraAllowsAccessToApplicationCheck() { let authorizationStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) switch authorizationStatus { case .NotDetermined: // permission dialog not yet presented, request authorization AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted:Bool) -> Void in if granted { print("access granted", terminator: "") } else { print("access denied", terminator: "") } }) case .Authorized: print("Access authorized", terminator: "") case .Denied, .Restricted: alertToEncourageCameraAccessWhenApplicationStarts() default: print("DO NOTHING", terminator: "") } } //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 { dispatch_async(dispatch_get_main_queue()) { UIApplication.sharedApplication().openURL(url) } } } let cancelAction = UIAlertAction(title: "Okay", style: .Default, handler: nil) internetUnavailableAlertController .addAction(settingsAction) internetUnavailableAlertController .addAction(cancelAction) self.window?.rootViewController!.presentViewController(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.sharedApplication().openURL(url) } } let cancelAction = UIAlertAction(title: "Okay", style: .Default, handler: nil) cameraUnavailableAlertController .addAction(settingsAction) cameraUnavailableAlertController .addAction(cancelAction) self.window?.rootViewController!.presentViewController(cameraUnavailableAlertController , animated: true, completion: nil) } } 

Aquí hay un fragmento pequeño y simple que suelo usar.

 - (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]); } 

Swift 2.0+

Basado en una combinación de respuestas aquí, he creado una solución para mí. Este método solo verifica si no hay permiso.

Tenemos un método pickVideo() que requiere acceso a las fotos. Si no lo es. .Authorized solicite permiso.

Si no se otorga el permiso, no se pickVideo() y el usuario no podrá elegir un video.

Siempre y cuando el usuario no haya otorgado acceso completo a las fotos, puede evitar dejar que elijan o bloqueen su aplicación.

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