1

I have a dictionary with keys that have multiple values. On the first view controller, I want the keys of the dictionary to be the table view cell's text, one for each row. Depending on which row (that has a dictionary key as a label) is selected I want that key's values to be the text of the table view cell's on the following view controller. Almost like a nested set up. So if you pick one row with a specific key as its text, the next view controller's table view will display its values in another table view. Similar to the settings tab on the iPhone, if you select a row that has one title that display its options, in the following view controller you will always ONLY get those options. What's the best way to implement this, I've been trying for a long time with no avail. Right now my current code gets an error that says index out of range.

Here's code for first view controller:

  import UIKit

  var trainingDict = ["Ball Handling" : ["1 Ball Stationary Drills", "1 Ball Combo Moves", "2 Ball Stationary Drills", "2 Ball Combo Moves", "2 Ball Partner Drills", "Handle Hoop Drills", "Placeholder"], "Shooting" : ["Form Shooting", "Spot Shooting", "Off The Dribble Shots", "Pull Up Jumpshots", "Catch & Shoots", "Free Throws", "Partner Shooting"], "Defense" : ["5 Star Drill", "Full Court Def. Slides", "1 v 1 Closeouts", "Gauntlet Drill", "Tennis Ball Reaction Drill", "Lane Slides", "Place Holder"], "Advanced Drills" : ["D Man Series", "Iso Series", "Double Move Series", "Gauntlet Series", "John Wall Drill", "Floater Series", "PlaceHolder"], "Vertimax Drills" : ["One Foot Jumps", "Box Jumps", "Resitance Slides", "Resistance Jumps", "Resistance Ball Handling", "Vertimax Sprints", "Slam Drill"], "Full Workouts" : ["Workout A", "Workout B", "Workout C", "Workout D", "Workout E", "Workout F", "Workout G"], "BHB Products" : ["Handle Hoops", "Handle Cubes", "Strech Bands", "Advocare", "Placeholder", "Placeholder2", "Placeholder3"]]
 var gradient : CAGradientLayer!
 var myIndex = 0


  class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {



@IBOutlet weak var tableView: TableView!

var trainingCategories = [String]()
var arrayForKey = [String]()
var selectedKey = String()




public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{

    return trainingDict.count
}




public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "bell" , for: indexPath) as! ViewControllerTableViewCell
    cell.tag = indexPath.row




    //cell details
    cell.backgroundColor = UIColor.clear

    //gradient details
    gradient = CAGradientLayer()
    gradient.frame = tableView.bounds
    gradient.colors = [UIColor.black.cgColor, UIColor.darkGray.cgColor, UIColor.black.cgColor]
    tableView.layer.insertSublayer(gradient, at: 0)
    gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
    gradient.endPoint = CGPoint(x: 1.0, y: 1.0)

    //details what the text label of cell displays
    var trainingCategories = Array(trainingDict.keys)
    trainingCategories.sort { return $0 < $1}
    cell.textLabel?.text = trainingCategories[indexPath.row]
    cell.textLabel?.textColor = UIColor.white

    return cell
}


func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    myIndex = indexPath.row
    selectedKey = trainingCategories[indexPath.row]
    performSegue(withIdentifier: "segue", sender: self)

}

  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "segue" {
        if let secondTableView = segue.destination as? DrillsViewController {

            //get array for selected key
            arrayForKey = trainingDict[selectedKey]!

            //pass to second table view
            secondTableView.arrayForKey2 = arrayForKey
            }
        }


    }



   override func viewDidLoad() {
    super.viewDidLoad()
    tableView.delegate = self
    tableView.dataSource = self
    var trainingCategories = Array(trainingDict.keys)
    trainingCategories.sort { return $0 < $1}
}

  override  func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

Second view controller code:

 import UIKit



 class DrillsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

var arrayForKey2 = [String]()

@IBOutlet weak var tableView: DrillsTableView!

@IBOutlet weak var drillLabel: UILabel!


public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{

    return arrayForKey2.count
}

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

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell" , for: indexPath) as! DrillsTableViewCell

    //clear background color needed in order to display gradient cell
    cell.backgroundColor = UIColor.clear

    //gradient configuration
    gradient = CAGradientLayer()
    gradient.frame = tableView.bounds
    gradient.colors = [UIColor.black.cgColor, UIColor.darkGray.cgColor, UIColor.black.cgColor]
    tableView.layer.insertSublayer(gradient, at: 0)
    gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
    gradient.endPoint = CGPoint(x: 1.0, y: 1.0)



    //attributes for watch/play button
    cell.playButton.layer.shadowColor = UIColor.yellow.cgColor
    cell.playButton.layer.shadowOffset = CGSize(width: 2, height: 2)
    cell.playButton.layer.shadowOpacity = 0.7
    cell.playButton.layer.shadowRadius = 1

    //details for cell label display

    cell.drillTitle.text = "\(arrayForKey2[indexPath.row])"


    return cell
}




override func viewDidLoad() {
    super.viewDidLoad()
    tableView.delegate = self
    tableView.dataSource = self

       }
Captain Code
  • 277
  • 1
  • 3
  • 13

1 Answers1

0

You can pass what you want in performSegue, for example, the indexpath or key you select .

Since your data source of table view is a Dictionary. You can make it an Array to keep the index. (just like what you did in cellForRowAt)

// didSelectRowAt
let key = Array(trainingDict.keys)[indexPath.row]
performSegue(withIdentifier: "segue", sender: key)

// navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "segue" {
        guard let secondTableView = segue.destination as? DrillsViewController, let key = sender as? String else { return }

        secondTableView.arrayForKey2 = trainingDict[key]
    }
}
Willjay
  • 6,381
  • 4
  • 33
  • 58