Avec la nouvelle fonctionnalité d'iOS 8, si vous utilisez un appareil photo dans l'application, il vous demandera l'autorisation d'accéder à l'appareil photo, puis lorsque vous essayez de reprendre la photo, il vous demandera l'autorisation d'accéder à la photothèque. La prochaine fois que je lancerai l'application, je souhaite vérifier si la bibliothèque de l'appareil photo et des photos dispose des autorisations nécessaires pour y accéder.
Pour la caméra, je vérifie par
if ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] == AVAuthorizationStatusDenied)
{
// do something
}
Je cherche quelque chose de semblable à ceci pour la photothèque.
Check +[PHPhotoLibrary authorizationStatus]
- si non défini, il retournera PHAuthorizationStatusNotDetermined
. (Vous pouvez ensuite demander l'accès à l'aide de +requestAuthorization:
sur la même classe.)
Je sais que cela a déjà été répondu, mais juste pour développer la réponse @ Tim, voici le code dont vous avez besoin (iOS 8 et supérieur):
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.
}
N'oubliez pas de #import <Photos/Photos.h>
Si vous utilisez Swift 3.0 ou supérieur, vous pouvez utiliser le code suivant:
// 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.
}
N'oubliez pas de import Photos
Juste comme formalité, Swift 2.X version:
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
}
}
}
}
Et Swift 3/Swift 4 :
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
}
}
}
}
Voici un guide complet pour iOS 8 et supérieur (sans ALAssetLibrary):
Tout d’abord, nous devons fournir description de l’utilisation , car c’est maintenant required de PHPhotoLibrary.
Pour cela, nous devons ouvrir le fichier info.plist
, trouver la clé Privacy - Photo Library Usage Description
et lui donner une valeur. Si la clé n'existe pas, créez-la simplement.
Voici une image par exemple:
Assurez-vous également que la valeur de la clé Bundle name
n'est pas vide dans le fichier info.plist
.
Maintenant, quand nous avons une description, nous pouvons normalement demander une autorisation en appelant la méthode 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;
}
}];
NOTE 1:requestAuthorization
ne montre pas l'alerte à chaque appel. Il affiche une fois par temps, enregistre la réponse de l'utilisateur et la renvoie à chaque fois au lieu d'afficher à nouveau l'alerte. Mais comme ce n'est pas ce dont nous avons besoin, voici un code utile qui affiche toujours une alerte chaque fois que nous avons besoin d'une autorisation (avec redirection des paramètres):
- (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];
}
}];
}
});
}
Problème courant 1: Certains utilisateurs se plaignent cette application ne montre pas l'alerte après avoir apporté les modifications susmentionnées au fichier info.plist
.
Solution: Pour les tests, essayez de remplacer le Bundle Identifier
du fichier de projet par un autre, nettoyez et reconstruisez l’application. Si cela fonctionne, alors tout va bien, renommez-le.
Problème courant 2: Il existe un cas spécifique où les résultats d'extraction ne sont pas mis à jour (et les vues utilisant des images de ces demandes d'extraction restent vides en conséquence) lorsque l'application obtient les autorisations pour les photos, lors de l'exécution de telle qu'elle était promis dans la documentation.
En fait, cela se produit lorsque nous utilisons UN CODE INCORRECT comme ceci:
- (void)viewDidLoad {
if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
{
//Reloading some view which needs photos
[self reloadCollectionView];
// ...
} else {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status == PHAuthorizationStatusAuthorized)
[self reloadCollectionView];
// ...
}];
}
// ...
}
Dans ce cas, si l'utilisateur refuse d'accorder des autorisations sur viewDidLoad
, puis passe aux paramètres, est autorisé et revient à l'application, les vues ne seront pas actualisées car les demandes [self reloadCollectionView]
et de récupération n'ont pas été envoyées.
Solution: Il suffit d’appeler le [self reloadCollectionView]
et d’effectuer d’autres requêtes de récupération avant de demander une autorisation comme celle-ci:
- (void)viewDidLoad {
//Reloading some view which needs photos
[self reloadCollectionView];
if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
{
// ...
}
Je l'ai fait comme ça:
- (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;
}
}
Et j’envoie ce que je dois faire comme bloc en fonction du succès ou de l’échec.
UPDATE pour: Swift 3 IOS10
Remarque: importez des photos dans AppDelegate.Swift comme suit
// AppDelegate.Swift
importer UIKit
importer Photos
...
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)
}
Réponse mise à jour de Alvin George
Utiliser ALAssetsLibrary devrait fonctionner:
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)
}
}
Voici un petit extrait simple que j'utilise habituellement.
- (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+
Sur la base d'une combinaison de réponses ici, j'ai créé une solution pour moi-même. Cette méthode vérifie uniquement s'il n'y a pas d'autorisation.
Nous avons une méthode pickVideo()
qui nécessite un accès aux photos. Si ce n'est pas .Authorized
, demandez la permission.
Si l'autorisation n'est pas donnée, pickVideo()
ne sera pas appelé et l'utilisateur ne pourra pas choisir une vidéo.
Tant que l'utilisateur ne donne pas un accès complet aux photos, vous pouvez éviter de les laisser choisir ou bloquer votre application.
// 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)
}
}
}