Как сгруппировать массив дат по месяцам и годам и показать в tableView?
Я работаю над приложением для учёта расходов и доходов для iOS. Я хочу, чтобы по нажатию на кнопку, в tableView появлялась новая секция с месяцем и годом, а в ней дата, которую я выбрал в datePicker. Естественно, если я выберу дату с другим месяцем, создавалась новая секция. Пока у меня получилось группировать даты по нажатию кнопки, но когда я повторно нажимаю на кнопку, секции дублируются. Вот мой код:
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var datePicker: UIDatePicker!
@IBOutlet weak var createButton: UIButton!
let formatter = DateFormatter()
var dateArray: [Date] = []
var result = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
formatter.dateFormat = "yyyy/MM/dd HH:mm"
formatter.locale = Locale(identifier: "ru_RU")
self.tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "TableViewCell")
}
func sorted() {
let sortedDateArr = dateArray.sorted { $0.compare($1) == .orderedAscending }
var tempArr = [String]()
for (index, date) in sortedDateArr.enumerated() {
tempArr.append(formatter.string(from: date))
if index + 1 < sortedDateArr.count {
if let days = Calendar.current.dateComponents([.day], from: date, to: sortedDateArr[index + 1]).day, days > 1 {
result.append(tempArr)
tempArr = []
}
} else {
result.append(tempArr)
}
}
}
@IBAction func createButtonAction(_ sender: Any) {
dateArray.append(datePicker.date)
sorted()
tableView.reloadData()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return result.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "\(result[section].last!)"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return result[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
cell.labelCell.text = "\(result[indexPath.row][indexPath.row])"
return cell
}
}
Ответы (1 шт):
Автор решения: schmidt9
→ Ссылка
Так происходит потому что вы не удаляете старые данные из массива result, все время добавляя туда новые. Я переработал ваш пример, добавив модели данных для удобства
class ViewController: UIViewController {
class Record : Comparable {
let calendar: Calendar = {
var calendar = Calendar.autoupdatingCurrent
calendar.locale = Locale(identifier: "ru_RU")
return calendar
}()
var date: Date
init(date: Date) {
self.date = date
}
// MARK: Equatable and Comparable for sorting
static func == (lhs: Record, rhs: Record) -> Bool {
lhs.date == rhs.date
}
static func < (lhs: Record, rhs: Record) -> Bool {
lhs.date < rhs.date
}
}
class Section : Record {
private let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM"
formatter.locale = Locale(identifier: "ru_RU")
return formatter
}()
var title: String {
formatter.string(from: date)
}
var items = [SectionItem]()
func addRecord(_ record: SectionItem) {
items.append(record)
}
}
class SectionItem : Record {
private let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm"
formatter.locale = Locale(identifier: "ru_RU")
return formatter
}()
var year: Int {
calendar.component(.year, from: date)
}
var month: Int {
calendar.component(.month, from: date)
}
var title: String {
formatter.string(from: date)
}
}
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var datePicker: UIDatePicker!
@IBOutlet weak var createButton: UIButton!
var items = [SectionItem]()
var sections = [Section]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func sortData() {
if items.isEmpty {
return
}
// prepare and reset data
items.sort()
sections = []
var year = 0
var month = 0
var section: Section!
for item in items {
// create new section for each month in each year
if section == nil || item.year != year || item.month != month {
section = Section(date: item.date)
sections.append(section)
}
section.addRecord(item)
year = item.year
month = item.month
}
}
@IBAction func createButtonAction(_ sender: Any) {
let dateRecord = SectionItem(date: datePicker.date)
items.append(dateRecord)
sortData()
tableView.reloadData()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].title
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell")!
cell.textLabel?.text = sections[indexPath.section].items[indexPath.row].title
return cell
}
}