0

So, I am trying to segue a button in storyboard to another ViewController. However, every time I tap the button, the app just crashes. This is the line of code that gets highlighted when the app crashes.

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

    let barcodeViewController: BarcodeReaderViewController = segue.destination as! BarcodeReaderViewController
    barcodeViewController.delegate = self

}

This is my BarCodeVC

import UIKit
import AVFoundation

protocol BarcodeDelegate {
  func barcodeReaded(barcode: String)
}

class BarcodeViewController: UIViewController, 
                             AVCaptureMetadataOutputObjectsDelegate {

var delegate: BarcodeDelegate?

var videoCaptureDevice: AVCaptureDevice = 
 AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
var device = AVCaptureDevice.defaultDevice(withMediaType: 
  AVMediaTypeVideo)
var output = AVCaptureMetadataOutput()
var previewLayer: AVCaptureVideoPreviewLayer?

var captureSession = AVCaptureSession()
var code: String?

override func viewDidLoad() {
  super.viewDidLoad()

  self.view.backgroundColor = UIColor.clear
  self.setupCamera()
}

private func setupCamera() {

  let input = try? AVCaptureDeviceInput(device: videoCaptureDevice)

  if self.captureSession.canAddInput(input) {
      self.captureSession.addInput(input)
  }

  self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

  if let videoPreviewLayer = self.previewLayer {
      videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
      videoPreviewLayer.frame = self.view.bounds
      view.layer.addSublayer(videoPreviewLayer)
  }

  let metadataOutput = AVCaptureMetadataOutput()
  if self.captureSession.canAddOutput(metadataOutput) {
      self.captureSession.addOutput(metadataOutput)

      metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
      metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code]
  } else {
      print("Could not add metadata output")
  }
}

 override func viewWillAppear(_ animated: Bool) {
   super.viewWillAppear(animated)

   if (captureSession.isRunning == false) {
      captureSession.startRunning();
   }
}

override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)

  if (captureSession.isRunning == true) {
     captureSession.stopRunning();
  }
}

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
   // This is the delegate'smethod that is called when a code is readed
   for metadata in metadataObjects {
       let readableObject = metadata as! AVMetadataMachineReadableCodeObject
       let code = readableObject.stringValue


       self.dismiss(animated: true, completion: nil)
       self.delegate?.barcodeReaded(barcode: code!)
       print(code!)
   }
 }
}

My segue is just a simple drag to show, not programmatically. So I am a bit confused as to why it's crashing.

Here's the error:

Could not cast value of type 'BarCodeProj.ViewController' (0x1000361b0) to 'BarCodeProj.BarcodeViewController' (0x100035a78).

insolence
  • 47
  • 6
  • Does the console happen to display the message "fatal error: unexpectedly found nil while unwrapping an Optional value"? – Daniel T. Jul 08 '17 at 19:36
  • No, it prints this in the console: Could not cast value of type 'BarCodeProj.ViewController' (0x1000361b0) to 'BarCodeProj.BarcodeReaderViewController' (0x100035a78). – insolence Jul 08 '17 at 19:38
  • Ah. There's your answer. – Daniel T. Jul 08 '17 at 19:41
  • In your storyboard, you didn't set correctly the class of the ViewController. – Larme Jul 08 '17 at 19:43
  • 1
    Possible duplicate of [Can't cast value of type UIViewController to PatternDetailViewController](https://stackoverflow.com/questions/31440964/cant-cast-value-of-type-uiviewcontroller-to-patterndetailviewcontroller) – Larme Jul 08 '17 at 19:44
  • @insolence: as a newbie developer your first best friend is the console. 2nd best is your brain (failed) attempt at understanding the error. The more you fail the better you become. 3rd best friend is Google. 4th best friend is Stakcoverflow previous questions 5th best friend is to ask your own question or leave comments on previous answers. The bad thing about the console is that it may have a lot of lines that contain meta date. Your job is to find the exact line that speaks to you. Words like **error**, **reason**, **exception** are the some common things you should look for. – mfaani Jul 08 '17 at 19:59
  • @Honey: thank you for the suggestions and friendly advice. I appreciate it and will be more attentive to those words. Thank you! – insolence Jul 08 '17 at 21:50

1 Answers1

2

This is a case where the console error tells you everything you need to know. segue.destination is not a BarcodeReaderViewController so your attempt to cast it to one (with as!) is causing a catastrophic failure.

First, check in your storyboard and make sure you set the type of the view controller properly (the one that you are transitioning to.)

Do this by selecting the appropriate view controller in the storyboard and checking here:

location where class name must be entered.

Daniel T.
  • 32,821
  • 6
  • 50
  • 72
  • Tried this. Made sure it was in the appropriate class. I did notice that my swift file and class names were different so I changed them to match (not sure how important that is). Sorry, I'm a beginner and still learning. I get the same crash with the same message in the console. Here's what the line of code looks like now: override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let barcodeViewController: BarcodeViewController = segue.destination as! BarcodeViewController barcodeViewController.delegate = self } – insolence Jul 08 '17 at 20:04
  • Got it! Had to check segue id before I set it as the destination. That's where my logic fell flat. But your answer guided me the way to make sure I matched the class name and VC file name. Thank you! You're awesome! – insolence Jul 08 '17 at 21:49