0

I'm trying to update a class variable (prediction) and then use that variable as data for a segue (AnalyzeSegue). However even if I update the class variable within the function (detectScene), the class variable is a nil value during prepare for segue causing my app to crash.

Most of the code was via this tutorial (just customized for my model):

https://www.raywenderlich.com/577-core-ml-and-vision-machine-learning-in-ios-11-tutorial

class PreviewViewController: UIViewController {

    var prediction: String?

    @IBOutlet weak var Photo: UIImageView!


//This button is what starts the segue into the next screen(
@IBAction func analyze(_ sender: Any) {}

override func prepare(for segue: UIStoryboardSegue, sender: Any?){

        if segue.identifier == "saveSegue"{
                           "save photo"}

        else if segue.identifier == "AnalyzeSegue"  #Analyze button

        {

            let AnalyzeVC = segue.destination as! AnalyzeViewController
              let ciImage = CIImage(image:Photo.image!)
             self.detectScene(image: ciImage!)
            print(self.prediction!) #nil value
            if let hasPrediction = self.prediction {
                AnalyzeVC.predictionLabel.text = hasPrediction
                AnalyzeVC.imagePreview.image = Photo.image}


}

detect function:

extension PreviewViewController{
    func detectScene(image: CIImage) {
        var localPrediction: String?

// Load the ML model through its generated class
        guard let model = try? VNCoreMLModel(for: test2().model)
            else {
            fatalError("can't load Places ML model")
                    }
        let request = VNCoreMLRequest(model: model) { [weak self] request, error in
            guard let results = request.results as? [VNCoreMLFeatureValueObservation]

                 else {
                    fatalError("unexpected result type from VNCoreMLRequest")
                        }
            let topResult = results.first?.featureValue.multiArrayValue
             DispatchQueue.main.async { () in
                var max_value : Float32 = 0        
                for i in 0..<topResult!.count{
                    if max_value < topResult![i].floatValue{
                        max_value = topResult![i].floatValue
                        localPrediction = String(i)

                                                            }

                                                } //#end of loop

                self?.prediction = localPrediction #update self?.prediction
                print(self?.prediction, "Inside Function") #seems to have value
                                        }   //#end of dispatch Queue 
       } //#end of closure

        let handler = VNImageRequestHandler(ciImage: image)
          DispatchQueue.global(qos: .userInteractive).async {
                do {
                    try handler.perform([request])

                   } catch {print(error)}


                                                        }

                                                         } //end of function

                                                                } //end of extension

So the detectScene function is supposed to update the class variable prediction and the that info is used in the prepare for seugue function. The function seems to be update the value, as I have a print statement within the function was printing out an optional value:

  print(self?.prediction, "Inside Function")

Thank you for your help.

Moondra
  • 4,399
  • 9
  • 46
  • 104
  • 1
    This looks like another variation of the recurring *“the request is executed asynchronously, the function returns immediately, the closure is called later”* theme. – Martin R Aug 19 '18 at 20:22
  • Thank you. I think I understand. I got rid of the multithreading aspects. – Moondra Aug 21 '18 at 00:09

0 Answers0