1

I don't know where to start... I need a TableView to show Information, organized by dates. I created a Class "Model" to hold the data...

class Model: NSObject {

var start: Date?
var str: String?

override init()
{

}

init(start: Date, str: String) {

    self.start = start
    self.str = str

}

Creating Elements of that Class

let value1 = Model(start: Date1(), str: string1)
let value2 = Model(start: Date2(), str: string2)

Filling an Array of that Elements:

var array = [Model]()
array.append(value1, value2)

Populating the TableView How can I divide the array, for example into months, or workweeks and so on... I want the tableView to organize the data in sections !?

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

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let label = UILabel()
    label.text = "January", Febuary, e.g.
    return label
}


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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TC_Arbeitszeit
cell.label.text = ?

    return cell
}

Any help is greatly appreciated !

Wings
  • 2,398
  • 23
  • 46
mtacki
  • 27
  • 1
  • 7
  • "Creating Elements of that Class: `Date1()`, `Date2()`" do you mean `Date()` or maybe `date` and `date2`? – Ahmad F Nov 05 '18 at 12:19
  • Yes- I was just trying to illustrate that I mean different date values- My fault - that was confusing – mtacki Nov 05 '18 at 12:26
  • Possible duplicate of [How to group by the elements of an array in Swift](https://stackoverflow.com/questions/31220002/how-to-group-by-the-elements-of-an-array-in-swift) – Scriptable Nov 05 '18 at 13:02

3 Answers3

3

Use the dictionary group by functionality. You can organize your array to keys and values, the key will be your sections and the values will be your raw.

example for grouping by day:

extension Date {
    var day: Int? {
        let components = Calendar.current.dateComponents([.day], from: self)
        return components.day
    }
}

let array = [model1, model2]

let dict = Dictionary(grouping: array) { (model) -> Int in
    return model.start?.day ?? 0
}

for the example let say that the day of "start" parameter on model1 is Sunday and the day of "start" parameter on model2 is Monday

so the dict will group it like this:

[1: [model1], 2: [model2]]

now you can use the key as section and the values as rows

func numberOfSections(in tableView: UITableView) -> Int {
    return dict.keys ?? 0
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let day = dic.keys[section]
    let label = UILabel()
    label.text = String(day)
    return label
}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let key = dict[section]
    return dict[key].count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TC_Arbeitszeit
    let data = dict[indexPath.section]
    cell.label.text = String(data[indexPath.row].start.day)

    return cell
}
AlphaWulf
  • 354
  • 5
  • 11
TalBenAsulo
  • 131
  • 6
  • Great approach- this actually got me diggin deep into the dictionaries capabilities... learned a lot ! Thanks a bunch – mtacki Nov 06 '18 at 15:15
1

Right now your mode is a simple array. Since you want groupings, your model needs to change a little, so that it includes sections/groups. You might start with an dictionary of arrays, where the keys are, say, the month or workweek.

Have a look at Swift's reduce:into: where you can iterate over your existing array and break it down into such a dictionary.

Then sort the dictionary's keys into a 'sections' array. The count of this is your table view's section count. So now your model has a sections array, and a dictionary, dateInfo.

When the table view asks for a row, look up the key in the sections array, let key = sections[indexPath.section], then find the model item itself:

var dateInfo: [Date: [Model]]
var sections: [Date] // sorted
...
let sectionContent = dateInfo[key] as! [Model]
// rowCount is just sectionContent.count
let rowInfo = sectionContent[indexPath.row]
// populate cell...

Hopefully that's enough of a pointer to get you headed in the right direction.

Graham Perks
  • 23,007
  • 8
  • 61
  • 83
0

Based on your case, generating a 2d array would be an appropriate choice.

How to do it?

let transfomredArray = Array(Dictionary(grouping: array, by: { $0. start! }).values)

thus transfomredArray is an array of arrays, each array in should contain models with same date.

Therefore you can handle your tableview data source method based on that, example:

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

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let label = UILabel()
    let date = transfomredArray[section][0].start!
    label.text = "\(date)"
    return label
}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TC_Arbeitszeit
    cell.label.text = transfomredArray[indexPath.section][indexPath.row]

    return cell
}
Ahmad F
  • 30,560
  • 17
  • 97
  • 143