I have a func which that is putting two lists together into a dictionary. I want this dictionary to print each [String : String] into a new cell on my table view. I'm only getting one cell back, which I know why (returning one item). However I can not figure out how to access my dictionary list to return each item in the dictionary. Here is a picture of what I'm currently getting. Screenshot of current results
Here is my struct and funcs to get the items and put into a dictionary.
//struct for the dictionary that holds all meals
struct RootData: Codable {
var meals: [MealDetails]
}
//struct for dessert details of each meal
struct MealDetails: Codable {
var id: String
var name: String
var instructions: String?
var image: String?
var strIngredient1: String?
var strIngredient2: String?
var strIngredient3: String?
var strIngredient4: String?
var strIngredient5: String?
var strIngredient6: String?
var strIngredient7: String?
var strIngredient8: String?
var strIngredient9: String?
var strIngredient10: String?
var strIngredient11: String?
var strIngredient12: String?
var strIngredient13: String?
var strIngredient14: String?
var strIngredient15: String?
var strIngredient16: String?
var strIngredient17: String?
var strIngredient18: String?
var strIngredient19: String?
var strIngredient20: String?
var strMeasure1: String?
var strMeasure2: String?
var strMeasure3: String?
var strMeasure4: String?
var strMeasure5: String?
var strMeasure6: String?
var strMeasure7: String?
var strMeasure8: String?
var strMeasure9: String?
var strMeasure10: String?
var strMeasure11: String?
var strMeasure12: String?
var strMeasure13: String?
var strMeasure14: String?
var strMeasure15: String?
var strMeasure16: String?
var strMeasure17: String?
var strMeasure18: String?
var strMeasure19: String?
var strMeasure20: String?
enum CodingKeys: String, CodingKey {
case id = "idMeal"
case name = "strMeal"
case instructions = "strInstructions"
case image = "strMealThumb"
case strIngredient1, strIngredient2, strIngredient3, strIngredient4, strIngredient5, strIngredient6,
strIngredient7, strIngredient8, strIngredient9, strIngredient10, strIngredient11, strIngredient12,
strIngredient13, strIngredient14, strIngredient15, strIngredient16, strIngredient17, strIngredient18,
strIngredient19, strIngredient20
case strMeasure1, strMeasure2, strMeasure3, strMeasure4, strMeasure5, strMeasure6, strMeasure7, strMeasure8, strMeasure9, strMeasure10, strMeasure11, strMeasure12, strMeasure13, strMeasure14, strMeasure15, strMeasure16, strMeasure17, strMeasure18, strMeasure19, strMeasure20
}
func getAllIngredients() -> [String] {
var ingredients = [String]()
ingredients.append(strIngredient1 ?? "")
ingredients.append(strIngredient2 ?? "")
ingredients.append(strIngredient3 ?? "")
ingredients.append(strIngredient4 ?? "")
ingredients.append(strIngredient5 ?? "")
ingredients.append(strIngredient6 ?? "")
ingredients.append(strIngredient7 ?? "")
ingredients.append(strIngredient8 ?? "")
ingredients.append(strIngredient9 ?? "")
ingredients.append(strIngredient10 ?? "")
ingredients.append(strIngredient11 ?? "")
ingredients.append(strIngredient12 ?? "")
ingredients.append(strIngredient13 ?? "")
ingredients.append(strIngredient14 ?? "")
ingredients.append(strIngredient15 ?? "")
ingredients.append(strIngredient16 ?? "")
ingredients.append(strIngredient17 ?? "")
ingredients.append(strIngredient18 ?? "")
ingredients.append(strIngredient19 ?? "")
ingredients.append(strIngredient20 ?? "")
return ingredients.filter{!$0.isEmpty}
}
func getAllMeasures() -> [String] {
var measures = [String]()
measures.append(strMeasure1 ?? "")
measures.append(strMeasure2 ?? "")
measures.append(strMeasure3 ?? "")
measures.append(strMeasure4 ?? "")
measures.append(strMeasure5 ?? "")
measures.append(strMeasure6 ?? "")
measures.append(strMeasure7 ?? "")
measures.append(strMeasure8 ?? "")
measures.append(strMeasure9 ?? "")
measures.append(strMeasure10 ?? "")
measures.append(strMeasure11 ?? "")
measures.append(strMeasure12 ?? "")
measures.append(strMeasure13 ?? "")
measures.append(strMeasure14 ?? "")
measures.append(strMeasure15 ?? "")
measures.append(strMeasure16 ?? "")
measures.append(strMeasure17 ?? "")
measures.append(strMeasure18 ?? "")
measures.append(strMeasure19 ?? "")
measures.append(strMeasure20 ?? "")
return measures
}
func getIngredientsAndMeasures() -> [String : String] {
var dictionary: [String : String] = [:]
let measures = getAllMeasures()
for (index, element) in getAllIngredients().enumerated() {
if !element.isEmpty {
dictionary[element] = measures[index]
}
}
return dictionary
}
}
Here is my view controller:
class DetailTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var idMeal: String = ""
var mealDetails = [MealDetails]()
//UI Oulets (Image, Dessert Name, Instructions, Ingredents)
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var instructionsText: UITextView!
@IBOutlet weak var detailTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
getApiDetailData {
print("data loaded")
self.view.reloadInputViews()
self.detailTableView.reloadData()
self.nameLabel.text = self.mealDetails[0].name
self.instructionsText.text = self.mealDetails[0].instructions
let urlString = (self.mealDetails[0].image)
let url = URL(string: urlString!)
self.imageView.downloaded(from: url!)
}
detailTableView.delegate = self
detailTableView.dataSource = self
}
func tableView(_ detailTableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mealDetails.count
}
func tableView(_ detailTableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
cell.textLabel?.text = "\(mealDetails[indexPath.row].getIngredientsAndMeasures())"
return cell
}
I've tried a number of things in the numbersOfRowsInSection function to access my dictionary. Any help would be much appreciated. I feel very close but not sure what I'm overlooking.
CodePudding user response:
I think you should use a custom type for each ingredient and measurement
struct Ingredient {
let name: String
let measurement: String
}
and then you add a function to create an array of them from a MealDetails object by adding this method to the struct
func createIngredients() -> [Ingredient] {
return zip(getAllMeasures(), getAllIngredients()).map {
if $0.0.isEmpty { return nil }
return Ingredient(name: $0.0, measurement: $0.1)
}
}
Then you can have a property for this array in your view controller
var ingredients = [Ingredient]()
and assign to it in the closure in viewDidLoad
self.ingredients = self.mealDetails[0].createIngredients()
and then use it as the data source for your table view
func tableView(_ detailTableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ingredients.count
}
func tableView(_ detailTableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
cell.textLabel?.text = "\(ingredients[indexPath.row].name)" // or whatever you want here
return cell
}