Medicine Man
Medicine Man

Reputation: 91

Creating TableView Sections from JSON Data Swift 4

My JSON data file is already alphabetized and is properly showing in my TableView. I set up my section titles using:

struct FigureStats: Decodable {
let name: String
let number: String
let year: String?
}

var figSectionTitles = [String]()
var figures = [FigureStats]()

override func viewDidLoad() {
super.viewDidLoad()
figSectionTitles = [String](arrayLiteral: "#", "A", "B", "C")
}

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

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

func downloadJSON(completed: @escaping () -> ()) {
    let url = URL(string: "https://xxxx")

    URLSession.shared.dataTask(with: url!) { (data, response, error) in
        if error == nil {
            do {
                self.figures = try JSONDecoder().decode([FigureStats].self, from: data!)
                DispatchQueue.main.async {
                    completed()
                }
            } catch {
                print("JSON Error")
            }
        }
    }.resume()
}

The problem is all of the entries are repeated inside each section instead of falling under the correct section based on the first character of each name.

How can get the first character of each name and then get those entries to fall under the correct section?

Upvotes: 1

Views: 2811

Answers (2)

RajeshKumar R
RajeshKumar R

Reputation: 15748

You can use init(grouping:by:) to group the array into Dictionary.

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {

    var figures = [Employee]()
var figuresByLetter = [(key: String, value: [Employee])]()
override func viewDidLoad() {
    super.viewDidLoad()
    figures = [Employee(name: "Kofi", year: 2000, id: 1),Employee(name: "Abena", year: 2002, id: 2),Employee(name: "Efua", year: 2003, id: 3),Employee(name: "Kweku", year: 2003, id: 3),Employee(name: "Akosua", year: 2003, id: 3)]
    figuresByLetter = Dictionary(grouping: figures, by: { String($0.name.trimmingCharacters(in: .whitespaces).first!) }).sorted(by: { $0.0 < $1.0 })
    print(figuresByLetter)
}
func numberOfSections(in tableView: UITableView) -> Int {
    return figuresByLetter.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return figuresByLetter[section].key
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return figuresByLetter[section].value.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
    cell.textLabel?.text = figuresByLetter[indexPath.section].value[indexPath.row].name
    return cell
}


}
struct Employee {
    var name:String?
    var year:Int?
    var id:Int?
}

Data after grouping

[(key: "A", value: [Employee(name: "Abena", year: 2002, id: 2), Employee(name: "Akosua", year: 2003, id: 3)]),
 (key: "E", value: [Employee(name: "Efua", year: 2003, id: 3)]),
 (key: "K", value: [Employee(name: "Kofi", year: 2000, id: 1), Employee(name: "Kweku", year: 2003, id: 3)])]

enter image description here

Upvotes: 5

CrazyPro007
CrazyPro007

Reputation: 1062

func numberOfSections(in tableView: UITableView) -> Int {
    return figuresByLetter.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let sectionTitle = figuresByLetter[indexPath.section]
    return sectionTitle 
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let sectionTitle = figuresByLetter[indexPath.section]
    //filteredArray = filter the array of figures based on current section value
    return filteredArray.count
}

Upvotes: 0

Related Questions