1

In order to practice my networking, I built an app with a text field where you can input something. I use the wikipedia API to fetch the definition of that term / name/ expression. My goal is to then display that definition into another view controller.

A button performs the segue to the new view controller, where a label displays that definition.

The get request works, but when tapping the button, I get a fatalError : "Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value".

I would like to add that the error is displayed in the "prepare for segue" function.

Here is the code for my first view controller

import UIKit
import Alamofire
import SwiftyJSON

class ViewController: UIViewController {

    @IBOutlet weak var textEntryLabel: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    //MARK: - Relevant variables
    let wikipediaURl = "https://en.wikipedia.org/w/api.php"
    var termDefinitionInfo: String = ""
    let segueName: String = "toDefinition"

    @IBAction func buttonToDefinition(_ sender: UIButton) {
        // on fait la requete ici
        httpCall(termDefinition: textEntryLabel.text ?? "nothing to pass")

        performSegue(withIdentifier: segueName , sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == segueName {
            let secondVC = segue.destination as! DefinitionViewController

            secondVC.definitionLabel.text = termDefinitionInfo

        }
    }

    //MARK: - NETWORKING

      func httpCall(termDefinition: String) {
          let parameters : [String:String] = [
                 "format" : "json",
                 "action" : "query",
                 "prop" : "extracts",
                 "exintro" : "",
                 "explaintext" : "",
                 "titles" : termDefinition,
                 "indexpageids" : "",
                 "redirects" : "1",
                 ]

          //
          request(wikipediaURl, method: .get, parameters: parameters).responseJSON { (response) in
              if response.result.isSuccess {
                //1. on affiche le tableau json initial
                let definitionJSON: JSON = JSON(response.result.value)
                print(definitionJSON)

                // deux valeurs : pageID et definition
                let pageId = definitionJSON["query"]["pageids"][0].stringValue
                let pageDefinition = definitionJSON["query"]["pages"][pageId]["extract"].stringValue
                self.termDefinitionInfo = pageDefinition
                print(self.termDefinitionInfo)

              } else {
                print("Error! Could not fetch data!")
            }
          }
      }


}

Here is the code for the second view controller

import SwiftyJSON
import Alamofire

class DefinitionViewController: UIViewController {

    @IBOutlet weak var definitionLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }


}```
LEKYSMA
  • 141
  • 10

1 Answers1

3

Tip: Try to avoid force down casting

In your case you are trying to assign a value to an IBOutlet when it's not wired to its parent view controller. You better do this:

class DefinitionViewController: UIViewController {
    @IBOutlet weak var definitionLabel: UILabel!
    var labelValue: String?

    override func viewDidLoad() {
        super.viewDidLoad()

        definitionLabel.text = labelValue
    }
}

And in your first view:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == segueName {
        if let secondVC = segue.destination as? DefinitionViewController {
          secondVC.labelValue = termDefinitionInfo
        }
    }
}
Maysam
  • 7,246
  • 13
  • 68
  • 106
  • 2
    I'm not totally agree with this *Tip: Try to avoid force down casting* if it's design mistake, then you will "*hide*" your bugs by scaring forcing. – vpoltave Dec 21 '19 at 14:08
  • i edited my code by following your advice @maysam and I no longer get an error in the 'prepare for segue'. however, I still do not manage to pass the data to the second view controller. – LEKYSMA Dec 22 '19 at 06:51
  • You don't get the passed data? How come? replace `var labelValue: String?` with `var labelValue: String? { didSet { print("*value set*") } }` and see if it prints anything in the console. – Maysam Dec 22 '19 at 09:55