确定是否设置了对照片库的访问 – PHPhotoLibrary
有了iOS 8中的新function,如果您在应用程序中使用相机,它将要求获得访问相机的权限,然后当您尝试重新拍摄照片时,它会要求获得访问照片库的权限。 下一次当我启动应用程序,我想检查相机和照片库是否有访问权限。
对于相机,我检查一下
if ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] == AVAuthorizationStatusDenied) { // do something }
我正在寻找类似于这个照片库的东西。
选中+[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
就像forms一样, 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 } } } }
“`
而斯威夫特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 } } } }
以下是iOS 8及以上版本(不含ALAssetLibrary)的完整指南:
首先,我们必须提供使用说明 ,现在它是PHPhotoLibrary所要求的。
要做到这一点,我们必须打开info.plist
文件,find关键Privacy - Photo Library Usage Description
并提供它的价值。 如果密钥不存在,只需创build它。
这里是一个图像例如:
还要确保info.plist
文件中的密钥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
实际上并不显示每个通话的警报。 它每隔一段时间显示一次,保存用户的答案并每次返回而不是再次显示警报。 但是,因为这不是我们所需要的,所以这是一个有用的代码,每次我们需要权限时都会显示警报(redirect到设置):
- (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
文件中做了上述变动之后,app不显示警报。
解决scheme:为了进行testing,请尝试将项目文件中的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]
和提取请求没有发送。
解决scheme:我们只需要调用[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; } }
而且我根据成败来发送我需要做的块。
使用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; } }
更新: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) }
答案从Alvin George更新
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+
基于这里的答案组合,我为自己创build了一个解决scheme。 此方法只检查是否没有权限。
我们有一个方法pickVideo()
需要访问照片。 如果不是,请授权。
如果没有给出权限, pickVideo()
将不会被调用,并且用户不能select一个video。
只要用户没有完全访问照片,您就可以避免让他们挑选或崩溃您的应用程序。
// 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) } } }
- UIButton上的iOS NSAttributedString
- UIButton标题alignment和多行支持
- 什么编程语言可以用来开发iPhone,iPod Touch和iPad(iOS)应用程序?
- 这个应用程序的开发人员还没有正确设置这个应用程序的Facebooklogin?
- 如何以编程方式使用iOS语音合成器? (文字转语音)
- 在UIScrollView中closures键盘
- iOS崩溃报告:atos不按预期工作
- NSGenericException“,原因是:只有在源控制器由UINavigationController实例pipe理时,才能使用Push segues
- embeddedYouTubevideo