0

I have a table with some items and sections for those items. Both the items and sections are hard-coded and I'm having a little trouble understanding how I could rather have everything loaded from one array rather than two.

Here is my code:

 import UIKit

class Beta: UIViewController, UITableViewDataSource, UITableViewDelegate{

    @IBOutlet weak var tableView: UITableView!


    let section = ["Fruits", "Vegetables"]
    let items = [["Apple", "Banana"], ["Carrots", "Broccoli"]]






    override func viewDidLoad(){
        super.viewDidLoad()
        self.tableView.allowsMultipleSelection = true




    }

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




    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return self.items[section].count
    }

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


    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?{
        return self.section[section]
    }


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

        cell.textLabel?.text = self.items[indexPath.section][indexPath.row]

        //MARK: -Checkmark and save support.
        cell.accessoryType = cell.isSelected ? .checkmark : .none
        cell.selectionStyle = .none // to prevent cells from being "highlighted"



        return cell
    }









}





}

I used code that I could find online and the only working code I could find had the sections and items seperate in two arrays.

How can I make it read everything off of this one array?

var Food:NSDictionary = [
        //:Section Title : Items
        "Fruits" : ["Apple","Banana"],
        "Vegetables" : ["Carrots","Broccoli"]
    ]

2 Answers 2

1

Try this -

struct Section {
 var name: String!
 var items: [String]!
 init(name: String, items: [String]) {
    self.name = name
    self.items = items
 }
}


import UIKit

class Beta: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet weak var tblView: UITableView!
var sections = [Section]()
override func viewDidLoad() {
    super.viewDidLoad()
    self.tblView.estimatedRowHeight = 56.0
    self.tblView.rowHeight = UITableViewAutomaticDimension
    self.tblView.tableFooterView = UIView()
     // Initialize the sections array
    sections = [
        Section(name: "Fruits", items: ["Apple", "Banana"]),
        Section(name: "Vegetables", items: ["Carrots", "Broccoli"]),
    ]
 }

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

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

    // For section 1, the total count is items count plus the number of headers
    var count = sections.count

    for section in sections {
        count += section.items.count
    }

    return count
   }

 // Add two prototype cell in your storyboard and give identifier "header" for header cell and "cell" for another one. 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell: UITableViewCell?
    // Calculate the real section index and row index
    let section = getSectionIndex(row: indexPath.row)
    let row = getRowIndex(row: indexPath.row)

        if row == 0 {
        let headerCell = tableView.dequeueReusableCell(withIdentifier: "header")! as UITableViewCell
        headerCell.textLabel?.numberOfLines = 0
        headerCell.textLabel?.textColor = UIColor.blue
        headerCell.textLabel?.lineBreakMode = .byWordWrapping
        headerCell.textLabel?.text = sections[section].name
        headerCell.selectionStyle = .none
        return headerCell
    } else {
            if cell == nil {
                cell = tableView.dequeueReusableCell(withIdentifier: "cell")
            }
        cell?.textLabel?.numberOfLines = 0
        cell?.textLabel?.lineBreakMode = .byWordWrapping
        cell?.selectionStyle = .none
        cell?.textLabel?.text = sections[section].items[row - 1]
        }
        return cell!
    }

//
// MARK: - Helper Functions
//
func getSectionIndex(row: NSInteger) -> Int {
    let indices = getHeaderIndices()

    for i in 0..<indices.count {
        if i == indices.count - 1 || row < indices[i + 1] {
            return i
        }
    }

    return -1
}

func getRowIndex(row: NSInteger) -> Int {
    var index = row
    let indices = getHeaderIndices()

    for i in 0..<indices.count {
        if i == indices.count - 1 || row < indices[i + 1] {
            index -= indices[i]
            break
        }
    }

    return index
}

func getHeaderIndices() -> [Int] {
    var index = 0
    var indices: [Int] = []

    for section in self.sections {
        indices.append(index)
        index += section.items.count + 1
    }

    return indices
   }


  }
Sign up to request clarification or add additional context in comments.

Comments

1

You're close, but you've mistakenly used a dictionary, which has no order. You need an array. It could be an array of one-item dictionaries, or even of tuples:

let arr : [(String, [String])] = ...

Even better, make a custom struct and use an array of that:

struct Model {
    let section : String
    let rows : [String]
}

Now your data is a [Model].

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.