У меня есть массив объектов, содержащих свойство Date. Я хочу распределить их в разделах UITableView в соответствии с их ежемесячным порядком. Как я могу это сделать?
Моя модель:
class Birthday: Object {
@objc dynamic var name: String = ""
@objc dynamic var date: Date = Date()
@objc dynamic var dayLeft: Int = 0
@objc dynamic var userImageData: Data?
}
Сначала я использую следующий код с DateFormatter:
var grouped: [String: [Birthday]] = [:]
grouped = Dictionary(grouping: birthdaysList) { item -> String in
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month], from: item.date)
let date = calendar.date(from: components) ?? Date(timeIntervalSince1970: 0)
return date.monthAsString()
}
extension Date {
func monthAsString() -> String {
let df = DateFormatter()
df.setLocalizedDateFormatFromTemplate("MMM")
return df.string(from: self)
}
}
Затем я использую:
struct Section {
let month: String
let birthdays: [Birthday]
}
var sections: [Section] = []
let keys = Array(grouped.keys)
sections = keys.map({Section(month: $0, birthdays: grouped[$0]!)})
Но мне нужно отсортировать названия месяцев по порядку. Январь, февраль и т.д. Как это можно сделать?
Я пытаюсь вернуть кортеж из своего кода, но получаю ошибку
Объявленный результат закрытия "(String, Int)" несовместим с контекстным типом "String"
grouped = Dictionary(grouping: birthdaysList) { item -> (String, Int) in
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month], from: item.date)
let date = calendar.date(from: components) ?? Date(timeIntervalSince1970: 0)
return (date.monthAsString(), components.month!)
}
Спасибо. Но, может быть, вы можете предоставить пример кода для моего случая?
На самом деле связанный ответ содержит пример. Сгруппируйте массив в словарь по году и месяцу.
Я добавил к моему примеру кода вопроса, который вы предоставили, но все равно не могу понять, как получить названия месяцев в разделах.
Создайте структуру-оболочку
struct Section {
let month : String
let birthdays : [Birthday]
}
затем сопоставьте сгруппированный словарь с массивом Section
let keys = Array(grouped.keys)
let sections = keys.map({Section(month: $0, birthdays: grouped[$0]!)})
sections
представляют разделы, birthdays
строки, month
заголовки разделов.
Редактировать:
Чтобы иметь возможность сортировать месяцы по их порядковому номеру, верните число перед названием месяца.
grouped = Dictionary(grouping: birthdaysList) { item -> String in
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month], from: item.date)
let date = calendar.date(from: components) ?? Date(timeIntervalSince1970: 0)
return "\(components.month!)_" + date.monthAsString()
}
И измените код сопоставления
let keys = grouped.keys.sorted{$0.localizedStandardCompare($1) == .orderedAscending}
let sections = keys.map({Section(month: $0.components(separatedBy:"_").last!, birthdays: grouped[$0]!)})
Я получаю сообщение об ошибке: Не удается преобразовать значение типа «[Любой]» в ожидаемый тип аргумента «[День рождения]»
Используйте собственные типы коллекций Swift.
Что это значит?
Ошибка не связана с данным кодом, возможно, вы где-то использовали NSArray
или забыли правильно преобразовать тип.
Но как я могу отсортировать месяцы по порядку? Я хочу, чтобы сначала был январь, затем февраль и т. д. Как это можно сделать?
Вместо того, чтобы возвращать строку, верните кортеж (String, Int)
из замыкания. Целочисленное значение является компонентом month
, тогда вы сможете правильно отсортировать массив.
Я пытаюсь, получаю ошибку: объявленный результат закрытия "(String, Int)" несовместим с контекстным типом "String"
Если вы заявляете item -> (String, Int) in
, вы должны вернуть return (date.monthAsString(), components.month!)
и наоборот.
Я пытаюсь, но все равно получаю ошибку: Объявленный результат закрытия "(String, Int)" несовместим с контекстным типом "String"
Добавил информацию к вопросу. В сгруппированном = Словарь (группировка: список дней рождения)
Связанный: stackoverflow.com/questions/52043162/…