Eirikurii
Eirikurii

Reputation: 45

Swift - Populating TableViews with multiple sections from multidimensional array

I am a beginner in Swift and have managed to understand at least the very basics of how to populate a UITableView. I am stuck now at populating multiple sections with data provided out of a dictionary.

I have a multidimensional Dictionary that assigns Objects to Categories:

var categoryDict:[String:[AnyObject]] = ["Category A": ["Object 1","Object 2"], "Category B":["Object 3"]]

Now I want to populate my TableView, so that it shows something like this:

So far I am able to create an array of categories to return the number of sections as well as to count the arrays stored in the dictionary to get the number of rows in each specific category. Now I am completely stuck at populating the TableView with sections and rows. How can I do this? Thank you very much!

My code so far:

var categoryList:[String] = [String]()
var categoryDict:[String:[AnyObject]] = ["Category A": ["Object 1","Object 2"], "Category B":["Object 3"]]


func getLists() {
    categoryList = Array(categoryDict.keys)
    categoryList.sortInPlace(before)
}

// Sort Array
func before(value1: String, value2: String) -> Bool {
    return value1 < value2;
}

func getNumberOfEntrysInSection (Section: Int) -> Int {

    let category:String = categoryList[Section]    //Get Category for Index in CategoryList

    let value:[AnyObject] = categoryDict[category]! //Get Value for this specific Category

    let number = value.count

    return number
}


// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    getLists()
    return categoryList.count
}


override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return getNumberOfEntrysInSection(section)
}


override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return categoryList[section]
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("BufferCell", forIndexPath: indexPath)

    ???
    return cell
}

Upvotes: 2

Views: 5840

Answers (1)

Duncan C
Duncan C

Reputation: 131398

First off: A dictionary is a poor choice for storing table view contents. Dictionaries are inherently unordered, so you have to keep sorting the keys. If your data gets beyond a small number of items that sort process will take appreciable time.

If you are going to use a dictionary anyway you should refactor your code so that you keep the sorted keys and use them over and over unless the dictionary changes. I would make it so that you add a setter method to the dictionary and always use that setter to change the dictionary. The setter method would regenerate the sorted keys. That way you only have to sort the keys if the dictionary changes. (But better to get rid of the dictionary entirely.)

I would suggest creating a Section object that contains a sectionTitle String and a sectionEntries Array. Then make the table view data an array of Section objects.

However, since you have a dictionary, I'll show you how to make that code work.

You need help with your cellForRowAtIndexPath method. You are almost there. You just need to fetch the appropriate entry in your data structure using the indexPath section and row. Something like this:

override func tableView(tableView: UITableView, 
  cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
{

    let cell = tableView.dequeueReusableCellWithIdentifier("BufferCell",
     forIndexPath: indexPath)
    let section = indexPath.section 
    let row = indexPath.row

    let categoryKey:String = categoryList[section]   
    let aCategoryEntry:[String] = categoryDict[categoryKey] as! [String]
    let anObject = aCategoryEntry[row] //
    let cell.textLabel.text = anObject
    return cell
}

Upvotes: 2

Related Questions