2

I am trying to pass a string of data through a segue. The JSON data has been parsed using JSONDecoder and appears properly in the console. Everything is working fine except for when I try to pass the data to a details ViewController I either receive no data or an error. I am using prepareForSegue to pass the data.

Here is the code for the ViewController:

var nowPlaying = [Results]()
var searchTitle = [Results]()

struct NowPlaying: Codable {
    let results: [Results]
}

struct Results: Codable {
    let title: String
    let poster_path: String?
    let id: Int
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    var films: [Results]

    if searchBar.text == "" {
        films = [nowPlaying[indexPath.row]]
    }

    print("\(films)")

    performSegue(withIdentifier: "detailsSegue", sender: films)

}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "detailsSegue" {
        if let detailView = segue.destination as? DetailsView {
                let filmCell = sender as? Results
                detailView.filmId = filmCell!.id
                print("\(filmCell!.id)")
        }
    }
}

I get an error at the detailView.filmId = filmCell.id

Cannot assign value of type 'Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

This is what prints to the console for print("\(films)"):

[Film_Bee.FilmsViewController.Results(title: "Venom", poster_path: 
Optional("/2uNW4WbgBXL25BAbXGLnLqX71Sw.jpg"), id: 335983)]

Nothing prints for print("\(filmCell!.id)")

I'm not sure why it's not finding the id within the results if its being found when parsed and when the cell is selected.

Here is my code from DetailsView:

class DetailsView: UIViewController {

let homepage = FilmsViewController()

var filmId = 0

var filmDetails = [Details]()

struct Results: Codable {
    let title: String
    let poster_path: String?
    let id: Int
}

struct Details: Codable {
    let title: String
    let poster_path: String
}

override func viewDidLoad() {
    super.viewDidLoad()

    print(filmId)

}
JSharpp
  • 459
  • 1
  • 9
  • 21

2 Answers2

3

You define

var films: [Results]

and then call

performSegue(withIdentifier: "detailsSegue", sender: films)

and then cast

let filmCell = sender as? Results

which will not work since Results is not [Results], decide if you want an array of Results or just one.

luk2302
  • 55,258
  • 23
  • 97
  • 137
  • if I try `let filmCell = sender as? [Results]` I get the error `Value of type '[FilmsViewController.Results]' has no member id` on the next line. – JSharpp Oct 09 '18 at 18:00
  • @JSharpp which is true since an array has no `id` property, only individual films have, **decive what you want: an array or an instance**. – luk2302 Oct 09 '18 at 18:01
  • Ok, so I change `var films: [Results]` to `var films: Results`. That works, thanks! – JSharpp Oct 09 '18 at 18:03
  • @JSharpp there you go :) probably with the changed assignment of `films = [nowPlaying[indexPath.row]]` => `films = nowPlaying[indexPath.row]` !? – luk2302 Oct 09 '18 at 18:04
  • Yeah and the same for the next line. Probably should have added that in there. – JSharpp Oct 09 '18 at 18:09
1

Reconsider your singular/plural naming. You want to pass one film, not an array

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    let film : Results // singular form `Result` is less confusing

    if searchBar.text.isEmpty {
        film = nowPlaying[indexPath.row]
    } else {
        film = searchTitle[indexPath.row]
    }

    print("\(film)")

    performSegue(withIdentifier: "detailsSegue", sender: film)

}
vadian
  • 274,689
  • 30
  • 353
  • 361