0

I'm trying to pass a Json response of an Http request from one controller to another, where in the second one I'd like to create a collection view from the recieved data.


import UIKit

class TableViewController: UITableViewController {

    let ingredientList = Ingredients().Ingredients
    public var arrayDrinks: Array<Any> = []
    let session = URLSession.shared


    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.reloadData()
        tableView.dataSource = self
        tableView.delegate = self

    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    // MARK: - number of rows
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.ingredientList.count
    }

    // MARK: - creating cell
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellaIng", for: indexPath)

        let singoloIngrediente = self.ingredientList[indexPath.row]

        cell.textLabel?.text = singoloIngrediente
        return cell
    }


    // MARK: - get the Selected Item
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        let selectedItem: String = ingredientList[indexPath.row]
        print("The selected ingredient is: \(selectedItem)")

        // parameter for http request
        let param = String(selectedItem.replacingOccurrences(of: " ", with: "_"))

        let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=\(param)")!

        // MARK: - Http request

        let task = session.dataTask(with: url) { data, response, error in

            if error != nil || data == nil {
                print("Client error!")
                return
            }

            guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                print("Server error!")
                return
            }

            do {
                // data from network request
                let decoder = JSONDecoder()
                let response = try decoder.decode(ObjectDrink.self, from: data!) // ObjectDrink from Model

                self.arrayDrinks.append(response.drinks)
                let destinationVC = DrinksListCollectionViewController()
                destinationVC.remoteArray = response.drinks
                 print("print array drink \(destinationVC.remoteArray)")

            } catch { print(error) }

        }
        performSegue(withIdentifier: "InglistSegue", sender: self)
         task.resume()

//        let destinationVC = DrinksListCollectionViewController()
//        destinationVC.remoteArray = self.arrayDrinks
//        destinationVC.performSegue(withIdentifier: "InglistSegue", sender: self)

    } // END didSelectRowAt

}

When I print the response to the console, the array of the second controller is empty, so no data is passing from the first response (array) to the other controller

Desdenova
  • 5,326
  • 8
  • 37
  • 45

2 Answers2

0

The view controller that you are moving to is not available yet and your line:

let destinationVC = DrinksListCollectionViewController()

Creates a new view controller which is not the one that your app transitions to. To use the view controller that will be shown, you use prepare(for segue: UIStoryboardSegue, sender: Any?) like so:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destinationVC = segue.destination as? DrinksListCollectionViewController {
        destinationVC.remoteArray = self.arrayDrinks
    }
}

Brojowski
  • 65
  • 7
0

You need to present it inside the callback of the URLSession.shared.dataTask like

DispatchQueue.main.async {
    self.arrayDrinks.append(response.drinks)
    let destinationVC = DrinksListCollectionViewController()
    destinationVC.remoteArray = response.drinks
    print("print array drink \(destinationVC.remoteArray)")
    self.present(destinationVC,animated:true,completion:nil)
}

If it's a segue then replace above with ( also inside the completion )

DispatchQueue.main.async {
  performSegue(withIdentifier: "InglistSegue", sender: response.drinks)
}

Add this method

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  let destinationVC = segue.destination as! DrinksListCollectionViewController 
  destinationVC.remoteArray = sender as! [Model] // model it type of drinks 
}
emrcftci
  • 3,355
  • 3
  • 21
  • 35
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • When you segue, you shouldn’t pass your data through the `sender` as it is for the object used to initiate the segue (ex: a UIButton). Pass the actual data to the destination view controller from a variable in the view controller instead. – Nathan Jul 23 '19 at 16:03
  • @Nathan can you read docs here https://developer.apple.com/documentation/uikit/uiviewcontroller/1621490-prepare for sender , actually it's of type `Any?` and it's widely used for sending the data instead of having to declare a variable , it's up to you as the developer to use it for anything according to your app structure and logic – Shehata Gamal Jul 23 '19 at 16:10