Stellen Sie fest, ob der Zugriff auf die Fotobibliothek festgelegt ist oder nicht - PHPhotoLibrary

100

Wenn Sie mit der neuen Funktion in iOS 8 eine Kamera in der App verwenden, werden Sie um Erlaubnis zum Zugriff auf die Kamera gebeten. Wenn Sie versuchen, das Bild erneut aufzunehmen, werden Sie um Erlaubnis zum Zugriff auf die Fotobibliothek gebeten. Wenn ich das nächste Mal die App starte, möchte ich überprüfen, ob die Kamera- und Fotobibliothek Zugriffsberechtigungen dafür hat.

Geben Sie hier die Bildbeschreibung ein

Für die Kamera überprüfe ich es durch

if ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] == AVAuthorizationStatusDenied)
{
// do something
}

Ich suche etwas Ähnliches für die Fotobibliothek.

tech_human
quelle

Antworten:

85

Aktivieren +[PHPhotoLibrary authorizationStatus]- Wenn nicht festgelegt, wird es zurückgegeben PHAuthorizationStatusNotDetermined. (Sie können dann den Zugriff mit +requestAuthorization:derselben Klasse anfordern .)

Tim
quelle
Muss ich eine Stiftung oder Bibliothek hinzufügen / importieren, um PHPhotoLibrary verwenden zu können? Ich
erhalte die
2
Ich habe stattdessen versucht, "ALAssetsLibrary" zu verwenden, um den Autorisierungsstatus zu überprüfen. Dies gibt JA zurück, auch wenn die Fotobibliothek deaktiviert ist.
tech_human
Oh, ich kann den Status mit "ALAssetsLibrary" abrufen. Immer noch neugierig zu wissen, ob es möglich ist, die PHPhoto-Bibliothek zu verwenden.
tech_human
3
PHPhotoLibrary ist Teil des Photos-Frameworks, das nur unter iOS 8 verfügbar ist. Wenn Sie Unterstützung für ältere Versionen von iOS benötigen, ist ALAssetsLibrary wahrscheinlich die beste Wahl.
Tim
Ab iOS 9 ist ALAssetsLibrary veraltet. Ich denke, deshalb funktioniert es nicht.
Supertecnoboff
130

Ich weiß, dass dies bereits beantwortet wurde, aber um die @ Tim-Antwort zu erweitern, ist hier der Code, den Sie benötigen (iOS 8 und höher):

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.
}

Vergiss es nicht #import <Photos/Photos.h>

Wenn Sie Swift 3.0 oder höher verwenden, können Sie den folgenden Code verwenden:

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

Vergiss es nicht import Photos

Supertecnoboff
quelle
5
Warum ist dies nur iOS 9 und höher? Fotos Framework ist seit iOS 8 verfügbar.
Balázs Vincze
1
Vergessen Sie auch nicht, das Photos Framework im Projekt -> Ziel -> Phasen
erstellen
Es funktioniert nicht richtig, ich habe den Zugriff verweigert und ihn dann wieder aktiviert, es heißt immer noch nicht bestimmt.
TomSawyer
"// Eingeschränkter Zugriff - normalerweise nicht." Warum? Es könnte passieren: "Der Benutzer kann den Status dieser Anwendung nicht ändern, möglicherweise aufgrund aktiver Einschränkungen"
NoKey
Nimmt PHPhotoLibrary.requestAuthorization an, dass ein Dialogfeld angezeigt wird, in dem um Erlaubnis gebeten wird? Weil das Recht, diese Leitung
anzurufen,
49

Genau wie die Formalität, 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
               }
            }
        }
    }

Und Swift 3 / Swift 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
                }
            }
        }
    }
Krodak
quelle
6
In Swift 3 vergessen import PhotosSie nicht, wenn Sie PHPhotoLibrary
ronatory
26

Hier ist eine vollständige Anleitung für iOS 8 und höher (ohne ALAssetLibrary):

Zuerst müssen wir eine Verwendungsbeschreibung bereitstellen, wie sie jetzt von PHPhotoLibrary benötigt wird.
Dazu müssen wir die info.plistDatei öffnen , den Schlüssel finden Privacy - Photo Library Usage Descriptionund einen Wert dafür bereitstellen. Wenn der Schlüssel nicht vorhanden ist, erstellen Sie ihn einfach.
Hier ist ein Bild zum Beispiel:
Geben Sie hier die Bildbeschreibung ein Stellen Sie außerdem sicher, dass der Wert des Schlüssels Bundle namein nicht leer istinfo.plist Datei ist.

Wenn wir nun eine Beschreibung haben, können wir normalerweise eine Autorisierung anfordern, indem wir die requestAuthorizationMethode aufrufen :

[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;
    }
}];

HINWEIS 1: requestAuthorization Tatsächlich wird nicht bei jedem Anruf eine Warnung angezeigt. Es wird einmal pro Zeit angezeigt, speichert die Antwort des Benutzers und gibt sie jedes Mal zurück, anstatt erneut eine Warnung anzuzeigen. Da dies jedoch nicht erforderlich ist, finden Sie hier einen nützlichen Code, der jedes Mal, wenn wir eine Berechtigung benötigen (mit Umleitung zu Einstellungen), eine Warnung anzeigt:

- (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];
                }
            }];
        }
    });
}

Häufiges Problem 1: Einige Benutzer beschweren sich dass die App nach den oben genannten Änderungen in der info.plistDatei keine Warnung anzeigt.
Lösung: Versuchen Sie zum Testen, Bundle Identifiervon der Projektdatei zu einer anderen zu wechseln , bereinigen Sie die App und erstellen Sie sie neu. Wenn es funktioniert hat, ist alles in Ordnung, benennen Sie es wieder um.

Häufiges Problem 2: Es gibt einen bestimmten Fall, in dem die Abrufergebnisse nicht aktualisiert werden (und die Ansichten, in denen Bilder aus diesen Abrufanforderungen verwendet wurden, immer noch entsprechend leer sind), wenn die App Berechtigungen für Fotos erhält, während sie wie in der Dokumentation versprochen ausgeführt wird.
Eigentlich passiert es, wenn wir FALSCHEN Code wie folgt verwenden:

- (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 diesem Fall werden viewDidLoadAnsichten nicht aktualisiert, wenn der Benutzer die Erteilung von Berechtigungen verweigert und dann zu den Einstellungen gesprungen, zugelassen und zur App zurückgesprungen ist, da keine Abrufanforderungen [self reloadCollectionView]gesendet wurden.
Lösung: Wir müssen nur anrufen [self reloadCollectionView]und andere Abrufanforderungen ausführen, bevor wir eine Autorisierung wie diese benötigen:

- (void)viewDidLoad {
    //Reloading some view which needs photos
    [self reloadCollectionView];
    if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
    {
        // ...
}
Nur Schatten
quelle
Wie verknüpfen Sie die Einstellungen der App mit Berechtigungen?
user2924482
20

Ich habe es so gemacht:

- (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;
    }
}

Und ich sende ein, was ich je nach Erfolg oder Misserfolg als Block tun muss.

Schatten
quelle
8

UPDATE für: SWIFT 3 IOS10


Hinweis: Importieren Sie Fotos in AppDelegate.swift wie folgt

// AppDelegate.swift

UIKit importieren

Fotos importieren

...


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)
}

Antwort von Alvin George aktualisiert

MLBDG
quelle
5

Die Verwendung von ALAssetsLibrary sollte funktionieren:

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;
    }
}
reich
quelle
3
Tolle Antwort, aber dies ist in iOS 9 veraltet.
Supertecnoboff
3
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)
    }
}
AG
quelle
0

Hier ist ein kleiner und einfacher Ausschnitt, den ich normalerweise benutze.

- (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]);
}
Camo
quelle
2
Es scheint nicht gewährt (JA) oder gewährt (NEIN) zurückzukehren, wenn es unbestimmt ist?
Shades
wie oben + Das starke Erfassen von 'Handler' in diesem Block führt wahrscheinlich zu einem Aufbewahrungszyklus
Ernest
0

Swift 2.0+

Basierend auf einer Kombination von Antworten hier habe ich eine Lösung für mich selbst erstellt. Diese Methode prüft nur, ob keine Berechtigung vorliegt.

Wir haben eine Methode pickVideo(), die Zugriff auf Fotos erfordert. Wenn es nicht .Authorizedum Erlaubnis bittet.

Wenn keine Erlaubnis erteilt wird, pickVideo()wird nicht aufgerufen und der Benutzer kann kein Video auswählen.

Solange der Benutzer keinen vollständigen Zugriff auf Fotos gewährt hat, können Sie vermeiden, dass er Ihre Anwendung auswählt oder abstürzt.

  // 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)
        }
      }
    }
Gerrit Post
quelle