Fotoğraf kitaplığına erişimin ayarlanıp ayarlanmadığını belirleyin - PHPhotoLibrary


101

İOS 8'deki yeni işlevsellik ile, uygulamada bir kamera kullanıyorsanız, kameraya erişmek için izin isteyecek ve ardından fotoğrafı yeniden çekmeye çalıştığınızda, fotoğraf kitaplığına erişmek için izin isteyecektir. Uygulamayı bir dahaki sefere başlattığımda, kamera ve fotoğraf kitaplığının ona erişim izinleri olup olmadığını kontrol etmek istiyorum.

görüntü açıklamasını buraya girin

Kamera için kontrol ediyorum

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

Fotoğraf kitaplığı için buna benzer bir şey arıyorum.

Yanıtlar:


85

Kontrol edin +[PHPhotoLibrary authorizationStatus]- ayarlanmadıysa geri dönecektir PHAuthorizationStatusNotDetermined. (Daha sonra +requestAuthorization:aynı sınıfta kullanarak erişim talebinde bulunabilirsiniz .)


PHPhotoLibrary'yi kullanmak için herhangi bir temel veya kitaplık eklemem / içe aktarmam gerekir mi? "
Belirtilmemiş

2
Yetkilendirme durumunu kontrol etmek için "ALAssetsLibrary" kullanmayı denedim ve bu, fotoğraf kitaplığı kapalı olsa bile YES döndürüyor.
tech_human

"ALAssetsLibrary" kullanarak durumu elde edebiliyorum. Yine de PHPhoto kitaplığını kullanmanın mümkün olup olmadığını merak ediyorum.
tech_human

3
PHPhotoLibrary, yalnızca iOS 8'de kullanılabilen Fotoğraflar çerçevesinin bir parçasıdır. İOS'un eski sürümleri için desteğe ihtiyacınız varsa, ALAssetsLibrary muhtemelen en iyi seçeneğinizdir.
Tim

İOS 9'da olduğu gibi, ALAssetsLibrary kullanımdan kaldırıldı, bu yüzden sanırım neden çalışmıyor.
Supertecnoboff

131

Bunun zaten yanıtlandığını biliyorum, ancak @Tim yanıtını genişletmek için ihtiyacınız olan kod burada (iOS 8 ve üstü):

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

Unutma #import <Photos/Photos.h>

Swift 3.0 veya üstünü kullanıyorsanız, aşağıdaki kodu kullanabilirsiniz:

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

Unutma import Photos


5
Bu neden yalnızca iOS 9 ve üstü? Fotoğraflar çerçevesi iOS 8'den beri kullanılabilir.
Balázs Vincze

1
Ayrıca Projeye Fotoğraf Çerçevesini eklemeyi unutmayın -> Hedef -> Yapım Aşamaları
stellz

Düzgün çalışmıyor, erişimi reddettim ve tekrar etkinleştirdim, yine de belirlenmedi diyor.
TomSawyer

"// Kısıtlı erişim - normalde olmayacak." Neden? Olabilir: "Kullanıcı, muhtemelen aktif kısıtlamalar nedeniyle bu uygulamanın durumunu değiştiremez"
NoKey

PHPhotoLibrary.requestAuthorization izin isteyen bir iletişim kutusu gösteriyor mu? Çünkü bu hattı doğru
aramak

50

Aynı formalite gibi, Swift 2.X versiyonu:

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

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

6
In Swift 3 unutmayın import PhotosEğer PHPhotoLibrary kullanmak istiyorsanız,
ronatory

27

İşte iOS 8+ için eksiksiz bir kılavuz (ALAssetLibrary olmadan):

Öncelikle şimdi PHPhotoLibrary tarafından gerekli olduğu gibi kullanım açıklamasını sağlamalıyız. Bunu yapmak için dosyayı açmalı , anahtarı bulmalı ve ona değer vermeliyiz . Anahtar yoksa, sadece oluşturun. Örneğin bir resim: Dosyada anahtar değerinin boş olmadığından da emin olun .
info.plistPrivacy - Photo Library Usage Description

görüntü açıklamasını buraya girinBundle nameinfo.plist

Artık açıklamamız olduğunda, normalde requestAuthorizationyöntemi çağırarak yetkilendirme isteyebiliriz :

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

NOT 1: requestAuthorization aslında her aramada uyarı göstermez. Her seferinde bir kez gösterir, kullanıcının cevabını kaydeder ve tekrar uyarı göstermek yerine her seferinde geri verir. Ancak ihtiyacımız olan şey bu olmadığından, her izne ihtiyacımız olduğunda her zaman uyarı gösteren yararlı bir kod burada (ayarlara yönlendirmeyle):

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

Yaygın sorun 1: Bazı kullanıcılar , dosyada yukarıda belirtilen değişiklikleri yaptıktan sonra uygulamanın uyarı göstermediğinden şikayetçiinfo.plist .
Çözüm: Test Bundle Identifieriçin proje dosyasından başka bir şeye geçmeyi deneyin , uygulamayı temizleyin ve yeniden oluşturun. Çalışmaya başladıysa, her şey yolunda, yeniden adlandırın.

Yaygın Sorun 2: Uygulama belgelerde vaat edildiği gibi çalışırken fotoğraflara izinler aldığında getirme sonuçlarının güncellenmediği (ve bu getirme isteklerinden gelen görüntüleri kullanan görünümler buna göre boş olduğu) bazı özel durumlar vardır .
Aslında şu şekilde YANLIŞ kod kullandığımızda olur :

- (void)viewDidLoad {
    if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
    {
        //Reloading some view which needs photos
        [self reloadCollectionView];
        // ...
    } else {
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status == PHAuthorizationStatusAuthorized)
                [self reloadCollectionView];
            // ...
        }];
    }
    // ...
}

Bu durumda, kullanıcı izin vermeyi reddetmiş ve viewDidLoadardından ayarlara geçmiş, izin vermiş ve uygulamaya geri dönmüşse, görünümler yenilenmeyecektir çünkü [self reloadCollectionView]ve getirme istekleri gönderilmemiştir.
Çözüm: Bunun [self reloadCollectionView]gibi yetkilendirme gerektirmeden önce başka getirme isteklerini aramalı ve yapmalıyız:

- (void)viewDidLoad {
    //Reloading some view which needs photos
    [self reloadCollectionView];
    if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
    {
        // ...
}

Uygulamanın ayarlarını izinlere nasıl bağlarsınız?
user2924482

20

Ben böyle yaptım:

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

Ve başarıya veya başarısızlığa bağlı olarak yapmam gerekeni blok olarak gönderiyorum.


8

GÜNCELLEME: SWIFT 3 IOS10


Not: Fotoğrafları AppDelegate.swift'e aşağıdaki gibi içe aktarın

// AppDelegate.swift

UIKit'i içe aktar

Fotoğrafları içe aktar

...


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

Yanıt, Alvin George tarafından güncellendi


5

ALAssetsLibrary kullanımı şu şekilde çalışmalıdır:

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

3
Harika yanıt, ancak bu iOS 9'da kullanımdan kaldırıldı.
Supertecnoboff

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

1

iOS 14 ve sonrası Apple, fotoğraf kitaplığına sınırlı erişim sağlayacak yeni bir özellik ekledi. Gereksinimlerinize bağlı olarak (Özel fotoğraf galerisi oluşturma örneği), kullanıcının yalnızca sınırlı erişim verip vermediğini ve tam erişim vermek isteyip istemediğini kontrol etmelisiniz.

Geriye dönük uyumluluk için, sınırlı erişime sahip olsanız bile parametresiz eski sürümler .authorized döndürür.

Swift 5 :

switch PHPhotoLibrary.authorizationStatus(for: .readWrite) {
case .notDetermined:
    // ask for access
case .restricted, .denied:
    // sorry
case .authorized:
    // we have full access
 
// new option: 
case .limited:
    // we only got access to some photos of library
}

Sınırlı erişim ekranını tekrar aramak için bir kod var. kullanıcı yalnızca .limited erişim verdiyse ve siz kullanıcının resimleri tekrar seçmesini istiyorsanız.

PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: presentVCObj)

Uygulamanın her yeniden başlatılmasında iOS, kullanıcıyı sınırlı erişim konusunda bilgilendirmek için bir uyarı gösterecektir. Bu uyarıyı durdurmak istiyorsanız PHPhotoLibraryPreventAutomaticLimitedAccessAlert, Info.plist içinde YES'e ekleyin .


0

İşte genellikle kullandığım küçük ve basit bir pasaj.

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

2
Belirsizse geri döndü (EVET) veya verildi (HAYIR) gibi görünüyor mu?
Shades

yukarıdaki gibi + bu blokta güçlü bir şekilde 'işleyiciyi' yakalamak bir tutma döngüsüne yol açacaktır
Ernest

0

Swift 2.0+

Buradaki cevapların kombinasyonuna dayanarak, kendim için bir çözüm yarattım. Bu yöntem yalnızca izin olup olmadığını kontrol eder.

pickVideo()Fotoğraflara erişim gerektiren bir yöntemimiz var . Değilse .Authorizedizin isteyin.

İzin verilmezse pickVideo()aranmaz ve kullanıcı video seçemez.

Kullanıcı fotoğraflara tam erişim vermediği sürece, uygulamanızı seçmelerine veya kilitlemelerine izin vermeyebilirsiniz.

  // 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)
        }
      }
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.