Определите, установлен ли доступ к библиотеке фотографий - PHPhotoLibrary
С новой функциональностью в iOS 8, Если вы используете камеру в приложении, он будет запрашивать разрешение на доступ к камере, а затем, когда вы пытаетесь пересдать pic, он запрашивает разрешение на доступ к библиотеке фотографий. В следующий раз, когда я запускаю приложение, я хочу проверить, если камера и фото библиотека имеет права доступа к нему.
для камеры, я проверяю его по
if ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] == AVAuthorizationStatusDenied)
{
// do something
}
Я ищу что-то похожее на это для библиотеки фотографий.
10 ответов:
Регистрация
+[PHPhotoLibrary authorizationStatus]
– Если не установлен, то он вернетPHAuthorizationStatusNotDetermined
. (Затем вы можете запросить доступ с помощью+requestAuthorization:
в том же классе.)
Я знаю, что на это уже ответили, но просто чтобы расширить ответ @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
так же формально,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:
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 } } } }
вот полное руководство для iOS 8 и выше (без ALAssetLibrary):
во-первых, мы должны обеспечить описание использования а теперь требуются по PHPhotoLibrary.
Для этого мы должны открытьinfo.plist
файл, найдите ключPrivacy - Photo Library Usage Description
и обеспечить ценность для него. Если ключ не существует, то просто создайте его.
Вот для примера:
Также убедитесь, что значение ключаBundle name
не пусто в .теперь, когда у нас есть описание, мы можем нормально запросить по телефону
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: некоторые пользователи жалуетесь это приложение не показывает предупреждение после выполнения вышеупомянутых изменений в .
Решение: для тестирования попробуйте изменить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) { // ... }
Я сделал это так:
- (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; } }
и я посылаю то, что мне нужно сделать в качестве блока в зависимости от успеха или неудачи.
обновление для: SWIFT 3 IOS10
Примечание: импорт фотографий в AppDelegate.Свифт следующим образом
/ / AppDelegate.Свифт
import 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) }
ответ обновлен от Элвин Джордж
использование 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; } }
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) } }
вот небольшой и простой фрагмент, который я обычно использую.
- (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+
основываясь на комбинации ответов здесь, я создал решение для себя. Этот метод проверяет только отсутствие разрешения.
у нас есть способ
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) } } }