Swift: Как создать массив массивов дат [[Date]] после сравнения / разбиения двух массивов дат [Date] - PullRequest
0 голосов
/ 04 декабря 2018

Введение

Я создаю приложение календаря, и мне нужно управлять массивом дат, чтобы предоставить данные для UITableView.

Контекст

Модель данных имеет тип [Date : [CalendarEvent]], где CalendarEvent - это подкласс NSManagedObject, который я сортирую в словарь, сгруппированный по атрибуту даты, связанному с событиями.И у меня есть один раздел для каждого ключа этого словаря в моем UITableView (я не получаю все события календаря сразу).Однако я хотел бы добавить больше разделов для отображения промежутков между датами с событиями, используя массив типа [[Date]]

  • Уточнение: представьте, что в моем приложении-календаре хранится 2 события.Одно событие 2018-12-05 и одно событие 2018-12-09, а сегодняшняя дата - 2018-12-01.В этом случае я хотел бы получить массив, подобный следующему: [ [2018-12-01, 2018-12-02, 2018-12-03, 2018-12-04], [2018-12-05], [2018-12-06, 2018-12-07, 2018-12-08], [2018-12-09], [2018-12-10] ], где каждая из этих дат имеет тип Date, конечно.(Что приведет к 4 разделам)

Вопрос

  • Как мне отсортировать / разбить мои массивы в соответствии с форматом [[Date]] (объяснено в "пояснение "выше)?
    • Если есть более простой способ достижения того же результата, это также будет рассматриваться как ответ.

Моя попытка

Я уменьшил масштаб, чтобы отобразить только необходимые детали.

class CalendarViewController: UIViewController {
    private let currentCalenar = Calendar.current
    var events : [Date: [CalendarEvent]]? // Events is fetched from todays date and 10 days forward.
    var sectionDates : [[Date]]?

    func getDatesWithEvents() -> [Date]? {
        if let keyArray = events?.keys {
            var dateArray = Array(keyArray)
            dateArray.sort { $0 < $1 }
            return dateArray
        }
        return nil
    }

    func getSectionDatesArray() -> [[Date]]? { 
        var sectionDatesArray : [[Date]] = []
        var currentDate = currentCalendar.startOfDay(for: Date())
        guard let endDate = currentCalendar.date(byAdding: .day, value: 9, to: currentDate), let datesWithEvent = getDatesWithEvents() else { return nil }
        while currentDate < endDate {
            if datesWithEvent.contains(currentDate) {
                sectionDatesArray.append([currentDate])
                sectionDatesArray.append([])
            } else {
                if !sectionDatesArray.isEmpty {
                    sectionDatesArray[sectionDatesArray.count - 1].append(currentDate)
                } else {
                    sectionDatesArray.append([currentDate])
                }
            }
            currentDate = currentCalendar.date(byAdding: .day, value: 1, to: currentDate)!
        }
        sectionDatesArray.removeAll { (sequence) -> Bool in
            sequence.isEmpty
        }
        return sectionDatesArray
   }

Спасибо за чтение моего вопроса.

1 Ответ

0 голосов
/ 04 декабря 2018

Как правило, использование нескольких источников данных на одном UITableView приносит неудачи. .. вы можете подумать об изменении своей модели данных.

В вашем примере я рассмотрел бы объединение этих двух источников данных таким образом, чтобы значения дат без событий были nil, поэтому вы бы объявили его как var dates: [Date: [CalendarEvent]?]?.

Другой способ - вы бы обрезали этот словарь и использовали массив для хранения объектов типа (рекомендуемое имя) CalendarItem - там вы можете хранить элементы Date и [CalendarEvent]?

Тем не менее, есть много способов сделать это, и я не собираюсь охватывать их все ...

Если вы хотите придерживаться своей модели, вот функция, которую я сделал.Это, вероятно, не оптимальное решение, и есть какая-то магия, которая может сделать это в 4 строки :), но здесь вы идете -

var currentDate = Date()

// just made up dates
let datesWithEvents: [Date] = [
    Calendar.current.date(byAdding: .day, value: 5, to: currentDate)!,
    Calendar.current.date(byAdding: .day, value: 10, to: currentDate)!
]

let endDate = Calendar.current.date(byAdding: .day, value: 15, to: currentDate)!

var dates: [[Date]] = []
while currentDate < endDate{

    if datesWithEvents.contains(currentDate){
        dates.append([currentDate])
        dates.append([])
    }else{

        if !dates.isEmpty{
            dates[dates.count - 1].append(currentDate)
        }else{
            dates.append([currentDate])
        }
    }

    currentDate = Calendar.current.date(byAdding: .day, value: 1, to: currentDate)!
}

/* prints
 [
    [
        2018-12-04 17:57:44 +0000
        2018-12-05 17:57:44 +0000
        2018-12-06 17:57:44 +0000
        2018-12-07 17:57:44 +0000
        2018-12-08 17:57:44 +0000
    ],
        [2018-12-09 17:57:44 +0000],
    [
        2018-12-10 17:57:44 +0000,
        2018-12-11 17:57:44 +0000,
        2018-12-12 17:57:44 +0000,
        2018-12-13 17:57:44 +0000
    ],
        [2018-12-14 17:57:44 +0000],
    [
        2018-12-15 17:57:44 +0000,
        2018-12-16 17:57:44 +0000,
        2018-12-17 17:57:44 +0000,
        2018-12-18 17:57:44 +0000
    ]
 ]
 */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...