1

For some reason my variables stringy and stringy are printing to the console just fine, but when I try to set them to a label, they show up as nil.

My goal is to print out the string and the float to the app view controller but this is just not working.

I think it has something to do with the viewdidload, as if its hiding the global variables. however if I try to set my label outside the viewdidload I get a declaration error.

//  ViewController.swift
//  Intellicam
//

import UIKit
import AVKit
import Vision

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {

    var stringy:String!
    var stringie:Float!

    override func viewDidLoad() {
        super.viewDidLoad()



        //here we start the camera

        let captureSession = AVCaptureSession()
        captureSession.sessionPreset = .photo
        guard let captureDevice = AVCaptureDevice.default(for: .video) else { return }
        guard let input = try? AVCaptureDeviceInput(device: captureDevice) else {return}
        captureSession.addInput(input)
        captureSession.startRunning()

        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        view.layer.addSublayer(previewLayer)
        previewLayer.frame = view.frame

        let dataOutput = AVCaptureVideoDataOutput()
        dataOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))
        captureSession.addOutput(dataOutput)

     //   let request = VNCoreMLModel(model: VNCoreMLModel, completionHandler: VNRequestCompletionHandler)
     //   VNImageRequestHandler(cgImage: <#T##CGImage#>, options: <#T##[VNImageOption : Any]#>)

        self.Labele.text = "Guess: \(stringy) + Certainty: \(stringie)"

    }

    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        //print("Camera was able to capture a frame:", Date())

        guard let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {return}

        guard let model = try? VNCoreMLModel(for: Resnet50().model) else {return}
        let request = VNCoreMLRequest(model: model){
            (finishedReq, err) in
            //print(finishedReq.results)

            guard let results = finishedReq.results as? [VNClassificationObservation] else {return}

             guard let firstObservastion = results.first else {return}


            //print("Guess: \(firstObservastion.identifier) Certainty: \(firstObservastion.confidence)%")

            self.stringy = firstObservastion.identifier
            self.stringie = firstObservastion.confidence

            print(self.stringy)
            print(self.stringie)

        }

        try? VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]).perform([request])
    }

    @IBOutlet weak var Labele: UILabel!


}
MontgommeryJR
  • 255
  • 3
  • 18
  • 1
    your request is **asynchronous**. You need to move the logic to set the label inside the completion of the request or have a completion for `captureOutput` method and handle it there. This should help - https://stackoverflow.com/questions/52287840/how-i-can-return-value-from-async-block-in-swift/52288141#52288141 – Rakesha Shastri Dec 06 '18 at 09:33
  • Just set the value of your label after you are sure that stringy and stringie are not nil. You can do that directly in the captureOutput function but it needs to be done in the main thread because it is a UI update. DispatchQueue.main.async { self.Labele.text = "Guess: \(stringy) + Certainty: \(stringie)" } – FedeH Dec 06 '18 at 09:41

1 Answers1

2

First thing is never use forcefully unwrap until you are sure about value. In your case VNCoreModelRequest can fail and your both variable will be un assigned so it will defiantly crash your app. One more thing make sure you use proper naming convention to your label.

Your issue is you are not setting label value from result you are getting.

To fix this

 var stringy:String? {
    didSet {
        DispatchQueue.main.async {
            self.Labele.text = self.stringy
        }
    }
}

OR

        self.stringy = firstObservastion.identifier
        self.stringie = firstObservastion.confidence
        DispatchQueue.main.async {
             self.Labele.text = "Guess: \(stringy) + Certainty: \(stringie)"
         }
Prashant Tukadiya
  • 15,838
  • 4
  • 62
  • 98