123

I have implemented a WKWebView in an app. there's a file input in the shown web page where it should import an image from photos. Whenever i press on that input and select either "Take Photo" or "Photo Library" the app suddenly crash, which I believe is because the app is missing the permission to either take a photo or import from library.

How do I push a permission request when the user select one of the mentioned methods (Take Photo or Photo Library)?

I use Swift 3.0 with WKWebView.

Kirit Modi
  • 23,155
  • 15
  • 89
  • 112
Alamri
  • 2,112
  • 2
  • 16
  • 21
  • 1
    @KiritModi Hi, thanks alot. Can you please post it as an answer so I can accept it. – Alamri Sep 22 '16 at 06:17
  • FYI: UIImagePickerController docs were never updated for this iOS10+ requirement (I skimmed every page, including the legacy Objective-C docs) – benc Nov 14 '17 at 18:20

10 Answers10

151

You can also request for access programmatically, which I prefer because in most cases you need to know if you took the access or not.

Swift 4 update:

    //Camera
    AVCaptureDevice.requestAccess(for: AVMediaType.video) { response in
        if response {
            //access granted
        } else {

        }
    }

    //Photos
    let photos = PHPhotoLibrary.authorizationStatus()
    if photos == .notDetermined {
        PHPhotoLibrary.requestAuthorization({status in
            if status == .authorized{
                ...
            } else {}
        })
    }

You do not share code so I cannot be sure if this would be useful for you, but general speaking use it as a best practice.

George Vardikos
  • 2,345
  • 1
  • 14
  • 25
  • 6
    Thanks, this answer worked for me! For people that are using Swift 4 the fist line should be changed to: "AVCaptureDevice.requestAccess(for: AVMediaType.video) { response in". – Kevin Nov 08 '17 at 15:58
  • 1
    Thanks for this answer. It works perfectly. I was wondering one thing about it though. When you run requestAuthorization does it create some kind of listener that waits until the permission is set before running it's code? At first I though that code execution simply stopped at PHPhotoLibrary.authorizationStatus but after dropping a bunch of print statements around it seems like it keeps going?? – George Kendros Nov 29 '17 at 02:22
  • 5
    **Swift 3**: `AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { response in`. Don't forget to `import AVFoundation`. – iurii Dec 13 '17 at 06:14
  • 2
    Thanks for the answer. Without it my app was rejected, because app could access photo library without permission. – Makalele Dec 18 '17 at 18:25
  • we still need to update the info.plist –  Mar 12 '22 at 21:19
134

You have to add the below permission in Info.plist. More Referance

Camera :

Key       :  Privacy - Camera Usage Description   
Value     :  $(PRODUCT_NAME) camera use

Photo :

Key       :  Privacy - Photo Library Usage Description    
Value     :  $(PRODUCT_NAME) photo use
Kirit Modi
  • 23,155
  • 15
  • 89
  • 112
  • Hi, I am actually having trouble getting iPhone7 users from setting photo library permission. When iPhone7 users go to my app settings on their phone, photo library option is missing. I have the Key:Value mentioned above in my info.plist. The weird part is all devices running iOS 10 are able to see this option, except iPhone7 users. iPhone6 running iOS 10 can see this option for example. Am I missing something else? – DevKyle Oct 05 '16 at 20:27
  • 1
    You shouldn't include the PRODUCT_NAME in these values, as that is already included in the Apple message. e.g. "App Name" Would Like to Access Your Photos – Elijah Jan 18 '17 at 05:53
91

Info.plist

Limited Photos

<key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
<true/>

Camera

<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) camera description.</string>

Photos

<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME)photos description.</string>

Save Photos

<key>NSPhotoLibraryAddUsageDescription</key>
<string>$(PRODUCT_NAME) photos add description.</string>

Location

<key> NSLocationWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) location description.</string>

Apple Music

<key>NSAppleMusicUsageDescription</key>
<string>$(PRODUCT_NAME) My description about why I need this capability</string>

Calendar

<key>NSCalendarsUsageDescription</key>
<string>$(PRODUCT_NAME) My description about why I need this capability</string>

Siri

<key>NSSiriUsageDescription</key>
<string>$(PRODUCT_NAME) My description about why I need this capability</string>
Vishal Vaghasiya
  • 4,618
  • 3
  • 29
  • 40
30

Use the plist settings mentioned above and the appropriate accessor (AVCaptureDevice or PHPhotoLibrary), but also alert them and send them to settings if you really need this, like so:

Swift 4.0 and 4.1

func proceedWithCameraAccess(identifier: String){
    // handler in .requestAccess is needed to process user's answer to our request
    AVCaptureDevice.requestAccess(for: .video) { success in
      if success { // if request is granted (success is true)
        DispatchQueue.main.async {
          self.performSegue(withIdentifier: identifier, sender: nil)
        }
      } else { // if request is denied (success is false)
        // Create Alert
        let alert = UIAlertController(title: "Camera", message: "Camera access is absolutely necessary to use this app", preferredStyle: .alert)

        // Add "OK" Button to alert, pressing it will bring you to the settings app
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
          UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!)
        }))
        // Show the alert with animation
        self.present(alert, animated: true)
      }
    }
  }
wjl
  • 7,143
  • 1
  • 30
  • 49
Joel Teply
  • 3,260
  • 1
  • 31
  • 21
28

File: Info.plist

For Camera:

<key>NSCameraUsageDescription</key>
<string>You can take photos to document your job.</string>

For Photo Library, you will want this one to allow app user to browse the photo library.

<key>NSPhotoLibraryUsageDescription</key>
<string>You can select photos to attach to reports.</string>
Ed of the Mountain
  • 5,219
  • 4
  • 46
  • 54
21

Swift 5 The easiest way to add permissions without having to do it programatically, is to open your info.plist file and select the + next to Information Property list. Scroll through the drop down list to the Privacy options and select Privacy Camera Usage Description for accessing camera, or Privacy Photo Library Usage Description for accessing the Photo Library. Fill in the String value on the right after you've made your selection, to include the text you would like displayed to your user when the alert pop up asks for permissions. Camera/Photo Library permission

elarcoiris
  • 1,914
  • 4
  • 28
  • 30
12

To ask permission for the photo app you need to add this code (Swift 3):

PHPhotoLibrary.requestAuthorization({ 
       (newStatus) in 
         if newStatus ==  PHAuthorizationStatus.authorized { 
          /* do stuff here */ 
    } 
})
marcomoreira92
  • 369
  • 3
  • 9
10

I wrote an extension that takes into account all possible cases:

  • If access is allowed, then the code onAccessHasBeenGranted will be run.
  • If access is not determined, then requestAuthorization(_:) will be called.
  • If the user has denied your app photo library access, then the user will be shown a window offering to go to settings and allow access. In this window, the "Cancel" and "Settings" buttons will be available to him. When he presses the "settings" button, your application settings will open.

Usage example:

PHPhotoLibrary.execute(controller: self, onAccessHasBeenGranted: {
    // access granted... 
})

Extension code:

import Photos
import UIKit

public extension PHPhotoLibrary {
   
   static func execute(controller: UIViewController,
                       onAccessHasBeenGranted: @escaping () -> Void,
                       onAccessHasBeenDenied: (() -> Void)? = nil) {
      
      let onDeniedOrRestricted = onAccessHasBeenDenied ?? {
         let alert = UIAlertController(
            title: "We were unable to load your album groups. Sorry!",
            message: "You can enable access in Privacy Settings",
            preferredStyle: .alert)
         alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
         alert.addAction(UIAlertAction(title: "Settings", style: .default, handler: { _ in
            if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
               UIApplication.shared.open(settingsURL)
            }
         }))
         DispatchQueue.main.async {
            controller.present(alert, animated: true)
         }
      }

      let status = PHPhotoLibrary.authorizationStatus()
      switch status {
      case .notDetermined:
         onNotDetermined(onDeniedOrRestricted, onAccessHasBeenGranted)
      case .denied, .restricted:
         onDeniedOrRestricted()
      case .authorized:
         onAccessHasBeenGranted()
      @unknown default:
         fatalError("PHPhotoLibrary::execute - \"Unknown case\"")
      }
   }
   
}

private func onNotDetermined(_ onDeniedOrRestricted: @escaping (()->Void), _ onAuthorized: @escaping (()->Void)) {
   PHPhotoLibrary.requestAuthorization({ status in
      switch status {
      case .notDetermined:
         onNotDetermined(onDeniedOrRestricted, onAuthorized)
      case .denied, .restricted:
         onDeniedOrRestricted()
      case .authorized:
         onAuthorized()
      @unknown default:
         fatalError("PHPhotoLibrary::execute - \"Unknown case\"")
      }
   })
}
dronpopdev
  • 797
  • 10
  • 13
  • hey @dronpop your solution is good and I used it, but when I install app first time and don't allow then app goes to crash. Can you please let me know how to resolve it? – Rana Ali Waseem Dec 31 '21 at 19:36
  • @RanaAliWaseem, I fixed the crash. Most likely you had the error described in [this](https://stackoverflow.com/questions/43071654/modifications-to-the-layout-engine-must-not-be-performed-from-a-background-threa) question. – dronpopdev Jan 02 '22 at 09:32
  • I get this crash iyziliOSApp[3585:195420] [Animation] +[UIView setAnimationsEnabled:] being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior. trace=( and then Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread. – Rana Ali Waseem Jan 02 '22 at 17:08
  • Yes as you mentioned question I'm getting this but how to fix it? – Rana Ali Waseem Jan 02 '22 at 17:10
  • @RanaAliWaseem [fix](https://stackoverflow.com/posts/61591120/revisions) – dronpopdev Jan 02 '22 at 17:39
  • there is fix please update answer. **DispatchQueue.main.async { onAccessHasBeenGranted() }** **DispatchQueue.main.async { onAuthorized() }** – Rana Ali Waseem Jan 12 '22 at 10:22
1

Add in your project’s info.plist these below keys with required string messages for Request Permissions:

Photos :

Privacy - Photo Library Additions Usage Description

Privacy - Photo Library Usage Description

Camera:

Privacy - Camera Usage Description

Better go and check everything in detail for learning at Apple’s Technology Documentation for all Protected resources (Bluetooth, Calendar, Camera & Microphone, Contacts Face ID , Location , Photos etc).

https://developer.apple.com/documentation/technologies

Go to above Link & Search :

Property List Keys -> Bundle Resources -> Information Property List -> Protected resources

Quick Guide Video for implementation in your Project

Thanks!:)

Abhimanyu Daspan
  • 1,095
  • 16
  • 20
0

Great way of implementing Camera session in Swift 5, iOS 13

https://github.com/egzonpllana/CameraSession

Camera Session is an iOS app that tries to make the simplest possible way of implementation of AVCaptureSession.

Through the app you can find these camera session implemented:

  • Native camera to take a picture or record a video.
  • Native way of importing photos and videos.
  • The custom way to select assets like photos and videos, with an option to select one or more assets from the Library.
  • Custom camera to take a photo(s) or video(s), with options to hold down the button and record.
  • Separated camera permission requests.

The custom camera features like torch and rotate camera options.

Egzon P.
  • 4,498
  • 3
  • 32
  • 31