-2

Objective: Pass an array of information from tableview to another tableview using the data created.

Problem: Couldn't access the array information from TableViewController in preparingForSegue

Result: TableViewController contains employee names, and when click on each of the employee, it goes to the details of showing arrays of information.

1) Employee.swift (model for data)

struct Employee {
    var name: String
    var food: [String]
    var ingredients: [String]

    init(name: String, food: [String], ingredients: [String]) {
        self.name = name
        self.food = food
        self.ingredients = ingredients
    }
}

2) TableViewController.swift (shows the name of the employee) Everything is working well here with the codes, the only thing that I am struggling here is passing the information to the next viewcontroller. In the comment section is where I tried typing destination.food = lists[indexPath.row].food. This didn't work as expected. I am trying to retrieve the array information.

class VillageTableViewController: UITableViewController {

    var lists : [Employee] = [
        Employee(name: "Adam" , food: ["Fried Rice","Fried Noodles"], ingredients: ["Insert oil, cook","Insert oil, cook"])]

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showVillages" {
            if let indexPath = self.tableView.indexPathsForSelectedRows {
                let destination = segue.destination as? DetailsViewController
                    // pass array of information to the next controller
            }
        }
    }

3) DetailsTableViewController.swift (shows an array of information) Code is working fine. I have the idea of creating an empty array and the information will be passed from TableViewController. In the comment section, I will then write cell.textLabel?.text = food[indexPath.row] and cell.subtitle?.text = ingredients[indexPath.row]

class DetailsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

var food:[String] = []
var ingredients:[String] = []
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! DetailsTableViewCell
    //this is where I will get the information passed from the array
    return cell
}

Please advise. I've been researching for the past few hours and couldn't figure it out yet. Bear in mind that all the code works fine here and I've only struggling in accessing the array information.

Edit: I am looking for arrays to be accessed and to be displayed on DetailsTableViewController.

Kelvin Tan
  • 327
  • 3
  • 15
  • When you say "This didn't work as expected" what actually happened – adamfowlerphoto Nov 30 '17 at 11:43
  • Daniel, the link showed string. I am looking for array. Please read the questions properly. – Kelvin Tan Nov 30 '17 at 12:36
  • @SwiftQuestions, it does not matter what _type_ of data you'd intend to pass between view-controllers via segue; if you create a completely custom datatype, you won't need to re-learn the concept of how to pass it over. – holex Nov 30 '17 at 14:26

3 Answers3

2

According to your question you are going to pass one item (the employee) to the detail view controller, not an array.

Do that:

  • In VillageTableViewController replace prepare(for with

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showVillages",
           let indexPath = self.tableView.indexPathForSelectedRow {
           let employee = lists[indexPath.row]
           let destination = segue.destination as! DetailsViewController
           destination.employee = employee
        }
    }
    
  • In DetailsViewController create a property employee

    var employee : Employee!
    

Now you can access all properties of the employee in the detail view controller, for example using its food array as data source

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return employee.food.count
}

and

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! DetailsTableViewCell
   cell.textLabel.text = employee.food[indexPath.row]
   return cell
}

PS: Rather than separate arrays for food (names) and ingredients I recommend to use a second struct (in this case you don't need to write any initializers in both structs)

struct Food {
    let name : String
    let ingredients: [String]
}


struct Employee {
    let name: String
    let food: [Food]
}

var lists : [Employee] = [
    Employee(name: "Adam" , food: [Food(name: "Fried Rice", ingredients:["Insert oil, cook"]),
                                   Food(name: "Fried Noodles", ingredients: ["Insert oil, cook"])])

The benefit is you can easily use sections in the detail view controller.

func numberOfSections(in tableView: UITableView) -> Int {
    return return employee.food.count
}

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let food = employee.food[section]
    return return food.name
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let food = employee.food[section]
    return food.ingredients.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! DetailsTableViewCell
   let food = employee.food[indexPath.section]
   cell.textLabel.text = food.ingredients[indexPath.row]
   return cell
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Hey Vadian, I tried let employee = lists[indexPath.row] and got the error of "Cannot subscript of value of type [Employee] with an index of type '[indexPath]' – Kelvin Tan Nov 30 '17 at 12:33
  • My suggested code uses `indexPathForSelectedRow`, your code `indexPathsForSelectedRows`, please note the difference – vadian Nov 30 '17 at 12:39
  • sorry! i just noticed that! let me try again. – Kelvin Tan Nov 30 '17 at 12:41
0

Having a closer look self.tableView.indexPathsForSelectedRows is an array of IndexPaths. Why don't you try

destination.food = lists[indexPath[0].row].food
adamfowlerphoto
  • 2,708
  • 1
  • 11
  • 24
0

In prepare set food according to selected employee from lists

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showVillages" {
        guard let indexPath = tableView.indexPathsForSelectedRow,
            let destinationVC = segue.destination as? DetailsViewController else {
            return
        }
        destinationVC.food = lists[indexPath.row].food
    }
}
Tomasz Czyżak
  • 1,118
  • 12
  • 13