web-dev-qa-db-fra.com

Problèmes d'autorisation de capture de photos dans iOS 11

Voici donc mon problème. J'essaie de créer un écran dans lequel il y a un UIImageView et un UIButton. Lorsque l'utilisateur appuie sur le bouton, l'application Appareil photo s'ouvre, vous prenez une photo et si vous appuyez sur "Utiliser la photo" dans l'application Appareil photo, vous revenez à l'écran de mon application et la photo est placée dans l'UIImageView que j'ai mentionné précédemment.

Ce qui se passe jusqu'à présent, c'est que lorsque j'appuie sur le bouton "Utiliser la photo", l'image est correctement placée dans mon UIImageView mais l'application se bloque avec l'erreur suivante:

Cette application s'est bloquée car elle a tenté d'accéder à des données sensibles à la confidentialité sans description d'utilisation. L'info.plist de l'application doit contenir une clé NSPhotoLibraryAddUsageDescription avec une valeur de chaîne expliquant à l'utilisateur comment l'application utilise ces données.

Ce que j'ai fait jusqu'à présent, c'est:

  1. Placer la clé "Confidentialité - Description de l'utilisation de la photothèque" avec la valeur "$ (PRODUCT_NAME) utilise la bibliothèque pour traiter les photos que vous avez capturées". dans le fichier Info.plist (également vérifié comment il est écrit sous forme de source et il est correct selon la Apple Documentation du développeur).

  2. Vous avez également placé la clé "Confidentialité - Description de l'utilisation de la caméra" avec la valeur "$ (PRODUCT_NAME) utilise des caméras" dans le fichier Info.plist.

  3. Vérifié sous "CIBLES -> -> Info-> Propriétés cibles iOS personnalisées" et les 2 paires clé/valeur que j'ai mentionnées aux étapes 1 et 2 existent.

Je vais vous fournir mon code jusqu'à présent:

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

Une idée pourquoi j'obtiens l'erreur ci-dessus en gras? Merci d'avance pour votre temps.

17

NSPhotoLibraryAddUsageDescription a été ajouté dans iOS 11.

Veuillez ajouter "Confidentialité - Description de l'utilisation des compléments de la bibliothèque de photos" dans info.plist avec une description d'utilisation (chaîne), comme vous l'avez fait pour les autres autorisations de confidentialité.

Réf: https://developer.Apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html

46
Kurt J