ios 确定是否设置了对照片库的访问 - PHPhotoLibrary
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26595343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Determine if the access to photo library is set or not - PHPhotoLibrary
提问by tech_human
With the new functionality in iOS 8, if you are using a camera in the app, it will ask for permission to access the camera and then when you try to retake the pic, it asks for permission to access photo library. Next time when I launch the app, I wish to check if the camera and photo library has access permissions to it.
使用 iOS 8 中的新功能,如果您在应用程序中使用相机,它会请求访问相机的权限,然后当您尝试重新拍摄照片时,它会请求访问照片库的权限。下次启动应用程序时,我希望检查相机和照片库是否具有访问权限。
For camera, I check it by
对于相机,我通过
if ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] == AVAuthorizationStatusDenied)
{
// do something
}
I am looking for something similar to this for photo library.
我正在为照片库寻找与此类似的东西。
采纳答案by Tim
Check +[PHPhotoLibrary authorizationStatus]
– if not set, it will return PHAuthorizationStatusNotDetermined
. (You can then request access using +requestAuthorization:
on the same class.)
检查+[PHPhotoLibrary authorizationStatus]
- 如果未设置,它将返回PHAuthorizationStatusNotDetermined
。(然后您可以+requestAuthorization:
在同一类上请求访问权限。)
回答by Supertecnoboff
I know this has already been answered, but just to expand on @Tim answer, here is the code you need (iOS 8 and above):
我知道这已经得到了回答,但只是为了扩展@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.
}
Don't forget to #import <Photos/Photos.h>
不要忘记 #import <Photos/Photos.h>
If you are using Swift 3.0 or higher, you can use the following code:
如果您使用的是 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.
}
Don't forget to import Photos
不要忘记 import Photos
回答by Krodak
Just as formality, Swift 2.Xversion:
就像形式一样,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
}
}
}
}
And Swift 3 / Swift 4:
和斯威夫特 3 / 斯威夫特 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
}
}
}
}
回答by Just Shadow
Here is a complete guide for iOS 8 and above (without ALAssetLibrary):
这是 iOS 8 及更高版本的完整指南(不含 ALAssetLibrary):
Firstly we have to provide usage descriptionas now it's requiredby PHPhotoLibrary.
For doing this we must open info.plist
file, find the key Privacy - Photo Library Usage Description
and provide value for it. If key doesn't exist then just create it.
Here is an image for example:Also make sure that value of key
Bundle name
is not empty in info.plist
file.
首先,我们必须提供使用说明,因为现在PHPhotoLibrary需要它。
为此,我们必须打开info.plist
文件,找到密钥Privacy - Photo Library Usage Description
并为其提供值。如果密钥不存在,则只需创建它。
例如,这是一个图像:还要确保文件中的键值
Bundle name
不为空info.plist
。
Now when we have description, we can normally request authorization by calling requestAuthorization
method:
现在当我们有了描述后,我们可以通过调用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
actually doesn't show alert on every call. It shows once per some time, saves user's answer and returns it everytime instead of showing alert again. But as it isn't what we need, here is a useful code which always shows alert every time we need permission (with redirection to settings):
注意 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];
}
}];
}
});
}
Common problem 1:Some users complainthat app doesn't show alert after doing above-mentioned changes in info.plist
file.
Solution: For testing try to change Bundle Identifier
from the project file to something else, clean and rebuild app. If it started working then everything is fine, rename it back.
常见问题一:部分用户抱怨在对info.plist
文件进行上述更改后,应用程序不显示警报。
解决方案:为了测试尝试Bundle Identifier
从项目文件更改为其他文件,清理并重建应用程序。如果它开始工作,那么一切都很好,重新命名它。
Common Problem 2:There is some specific case when fetch results are not updated (and the views which used images from those fetch requests still empty accordingly) when app gets permissions to photos, while runningas it was promised in the documentation.
Actually it happens when we use WRONGcode like this:
常见问题 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];
// ...
}];
}
// ...
}
In this case if user denied giving permissions on viewDidLoad
then jumped to settings, allowed and jumped back to app, views will not be refreshed because [self reloadCollectionView]
and fetch requests were not sent.
Solution: We just have to call [self reloadCollectionView]
and do other fetch requests before requiring authorization like this:
在这种情况下,如果用户拒绝授予权限,viewDidLoad
然后跳转到设置,允许并跳转回应用程序,则视图将不会刷新,因为[self reloadCollectionView]
未发送获取请求。
解决方案:我们只需要[self reloadCollectionView]
在要求授权之前调用并执行其他获取请求,如下所示:
- (void)viewDidLoad {
//Reloading some view which needs photos
[self reloadCollectionView];
if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
{
// ...
}
回答by Shades
I did it like this:
我是这样做的:
- (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;
}
}
And i send in what I need to do as the block depending on success or failure.
我根据成功或失败将我需要做的事情作为块发送。
回答by MLBDG
UPDATE for: SWIFT 3 IOS10
更新:SWIFT 3 IOS10
Note: import Photos in AppDelegate.swift as follows
注意:在 AppDelegate.swift 中导入照片如下
// AppDelegate.swift
// AppDelegate.swift
import UIKit
导入 UIKit
import 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)
}
Answer updated from Alvin George
从Alvin George更新的答案
回答by richy
Using ALAssetsLibrary should work:
使用 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;
}
}
回答by A.G
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)
}
}
回答by Gerrit Post
Swift 2.0+
斯威夫特 2.0+
Based on a combination of answers here, I've created a solution for myself. This method only checks if there is no permission.
基于这里的答案组合,我为自己创建了一个解决方案。此方法仅检查是否没有权限。
We got a method pickVideo()
that requires access to photos. If it is not .Authorized
ask for permission.
我们得到了一种pickVideo()
需要访问照片的方法。如果不是.Authorized
征求许可。
If permission is not given, pickVideo()
will not be called, and the user cannot pick a video.
如果未获得许可,pickVideo()
将不会被调用,并且用户无法选择视频。
As long as the user did not give full access to photos, you can avoid to let them pick 'or crash' your 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)
}
}
}
回答by Camo
Here is a small and simple snippet that I usually use.
这是我通常使用的一个小而简单的片段。
- (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]);
}