I'm wanting to store "idMeal" on the cell I click to send it through a segue to my DetailViewController and use it to access an API endpoint for the respective meal.
API with meal details that I'm trying to access for EACH meal when clicked on.
I believe I'm very close but I've been here for several hours.
Here are my structs:
//struct for the dictionary holding the desserts
struct DessertDictionary: Codable {
var meals: [Desserts]
}
//struct for all desserts
struct Desserts: Codable {
var strMeal: String?
var strMealThumb: String?
var idMeal: String?
}
//struct for dictionary holding the details
struct MealDataDictionary: Codable {
var meals: IndependentMealData
}
//struct for dessert details
struct IndependentMealData: Codable {
var idMeal: String
var strMeal: String
var strInstructions: String
}
Here is my first ViewController:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var mealList = [Desserts]()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
getApiData {
print("data loaded")
self.tableView.reloadData()
}
tableView.delegate = self
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mealList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
cell.textLabel?.text = "\(mealList[indexPath.row].strMeal!)"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetails", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? DetailTableViewController {
destination.idMeal = //NEED DATA HERE//
}
}
// MealApi.shared.getApiData(onCompletion: anonFunction)
func getApiData(completed: @escaping () -> ()) {
let url = URL(string: "https://www.themealdb.com/api/json/v1/1/filter.php?c=Dessert")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error == nil {
do {
// need to use the TopMeal struct to decode the json because it matches the structure of the json.
let jsonData = try JSONDecoder().decode(DessertDictionary.self, from: data!)
// after you decode the json you access the array within it to setup your array of meals instance variable that is being used by your table view.
self.mealList = jsonData.meals
DispatchQueue.main.async {
completed()
}
}
catch {
print(error)
}
}
}.resume()
}
}
Here is my DetailViewController where I am trying to pass the "idMeal" and use for the API pull for each cell, when clicked.
class DetailTableViewController: UITableViewController {
var idMeal: String = ""
var mealDatails: IndependentMealData?
//UI Oulets (Image, Dessert Name, Instructions, Ingredents)
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
func getApiDetailData(completed: @escaping () -> ()) {
let urlString = "https://www.themealdb.com/api/json/v1/1/lookup.php?i=\(idMeal)"
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error == nil {
do {
// need to use the TopMeal struct to decode the json because it matches the structure of the json.
let jsonData = try JSONDecoder().decode(MealDataDictionary.self, from: data!)
// after you decode the json you access the array within it to setup your array of meals instance variable that is being used by your table view.
self.mealDatails = jsonData.meals
// print(self.mealDatails?.idMeal)
DispatchQueue.main.async {
completed()
}
}
catch {
print(error)
}
}
}.resume()
}
}
If you need any extra information let me know, I've tried a number of things to access that data.
CodePudding user response:
I have to define the index the user tapped. E.g., just save the row and use it.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var mealList = [Desserts]()
var indexTapped: Int?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
indexTapped = indexPath.row
performSegue(withIdentifier: "showDetails", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? DetailTableViewController {
destination.idMeal = mealList[indexTapped!].idMeal
}
}
}