Photo capture permission problems in iOS 11

2019-01-23 14:08发布

So here's my problem. I am trying to create a screen in which there is a UIImageView and a UIButton. When the user presses the button, the camera app opens, you take a photo and if you press "Use Photo" in the Camera app, you are returned to my app's screen and the photo is placed in the UIImageView I mentioned previously.

What happens so far is that when I press the "Use Photo" button, the image is correctly placed in my UIImageView but then the app crashes with the following error:

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.

What I've done so far is:

  1. Placed the key "Privacy - Photo Library Usage Description" with the value "$(PRODUCT_NAME) uses Library in order to process the photos you captured." in the Info.plist file (also checked how it is written in Source form and it's correct according to the Apple Developer Documentation).

  2. Also placed the key "Privacy - Camera Usage Description" with the value "$(PRODUCT_NAME) uses Cameras" in the Info.plist file.

  3. Checked under "TARGETS->->Info->Custom iOS Target Properties" and the 2 key/value pairs that I mentioned in steps 1 and 2, exist.

I will provide you with my code so far:

import UIKit
import Vision
import MobileCoreServices
import AVFoundation
import Photos

class ViewController: UIViewController, UIImagePickerControllerDelegate, 
UINavigationControllerDelegate {

var newMedia: Bool?

@IBAction func captureImageButtonPressed(_ sender: Any) {
    //let imageName : String = "dolphin"
    //randomImageView.image = UIImage.init(named:imageName)

    if UIImagePickerController.isSourceTypeAvailable(
        UIImagePickerControllerSourceType.camera) {

        let imagePicker = UIImagePickerController()

        imagePicker.delegate = self
        imagePicker.sourceType =
            UIImagePickerControllerSourceType.camera
        imagePicker.mediaTypes = [kUTTypeImage as String]
        imagePicker.allowsEditing = false

        self.present(imagePicker, animated: true,
                     completion: nil)
        newMedia = true
    }
}

@IBAction func classifyButtonPressed(_ sender: UIButton) {
    performVisionRequest()
}
@IBOutlet weak var randomImageView: UIImageView!
@IBOutlet weak var classificationLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
}

func performVisionRequest() {
    let start = DispatchTime.now()
    let model = Resnet50()
    let request = VNImageRequestHandler(cgImage: randomImageView.image!.cgImage!, options: [:])
    do {
        let m = try VNCoreMLModel(for: model.model)
        let coreMLRequest = VNCoreMLRequest(model: m) { (request, error) in
            guard let observation = request.results?.first as? VNClassificationObservation else { return }
            let stop = DispatchTime.now()
            let nanoTime = stop.uptimeNanoseconds - start.uptimeNanoseconds
            let timeInterval = Double(nanoTime)
            self.classificationLabel.text = "\(observation.identifier) (\(observation.confidence * 100)%) in \(timeInterval) seconds."
        }
        try request.perform([coreMLRequest])
    } catch {
        print(error)
    }
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    let mediaType = info[UIImagePickerControllerMediaType] as! NSString
    self.dismiss(animated: true, completion: nil)
    if mediaType.isEqual(to: kUTTypeImage as String) {
        let image = info[UIImagePickerControllerOriginalImage]
            as! UIImage
        randomImageView.image = image
        if (newMedia == true) {
            UIImageWriteToSavedPhotosAlbum(image, self,
                                           #selector(ViewController.image(image:didFinishSavingWithError:contextInfo:)), nil)
        } else if mediaType.isEqual(to: kUTTypeMovie as String) {
            // Code to support video here
        }
    }
}

@objc func image(image: UIImage, didFinishSavingWithError error: NSErrorPointer, contextInfo:UnsafeRawPointer) {
    if error != nil {
        let alert = UIAlertController(title: "Save Failed",
                                      message: "Failed to save image",
                                      preferredStyle: UIAlertControllerStyle.alert)
        let cancelAction = UIAlertAction(title: "OK",
                                         style: .cancel, handler: nil)
        alert.addAction(cancelAction)
        self.present(alert, animated: true,
                     completion: nil)
    }
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    self.dismiss(animated: true, completion: nil)
}
}

Any idea why I get the above error in bold? Thank you very much in advance for your time.

1条回答
狗以群分
2楼-- · 2019-01-23 14:29

NSPhotoLibraryAddUsageDescription was added in iOS 11.

Please add "Privacy - Photo Library Additions Usage Description" in info.plist with a usage description (string), like you did for the other privacy permissions.

Ref: https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html

查看更多
登录 后发表回答