Determine if the access to photo library is set or not - PHPhotoLibrary

后端 未结 11 794
误落风尘
误落风尘 2020-11-27 10:23

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 f

相关标签:
11条回答
  • 2020-11-27 11:01

    I know this has already been answered, but just to expand on @Tim answer, here is the code you need (iOS 8 and above):

    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>

    If you are using Swift 3.0 or higher, you can use the following code:

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

    0 讨论(0)
  • 2020-11-27 11:02

    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.

    0 讨论(0)
  • 2020-11-27 11:05

    Using ALAssetsLibrary should work:

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 11:14

    UPDATE for: SWIFT 3 IOS10


    Note: import Photos in AppDelegate.swift as follows

    // AppDelegate.swift

    import 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

    0 讨论(0)
  • 2020-11-27 11:15

    Here is a complete guide for iOS 8+ (without ALAssetLibrary):

    Firstly we have to provide usage description as now it's required by 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.

    Now when we have description, we can normally request authorization by calling requestAuthorization method:

    [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):

    - (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 complain that 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.

    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 running as it was promised in the documentation.
    Actually it happens when we use WRONG code like this:

    - (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:

    - (void)viewDidLoad {
        //Reloading some view which needs photos
        [self reloadCollectionView];
        if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
        {
            // ...
    }
    
    0 讨论(0)
提交回复
热议问题