简体   繁体   English

Swift:在比较/分割两个日期数组[Date]之后,如何创建日期数组[[Date]]的数组

[英]Swift: How to create an array of date arrays [ [Date] ], after comparing/splitting two date arrays [Date]

Introduction 介绍

I'm creating a calendar app and I'm in need of managing of a date array in order to provide data for a UITableView . 我正在创建一个日历应用程序,并且需要管理一个日期数组以便为UITableView提供数据。

Context 语境

The data model is of type [Date : [CalendarEvent]] , where CalendarEvent is a NSManagedObject subclass that I sort into a dictionary grouped on the events associated date attribute. 数据模型的类型为[Date : [CalendarEvent]] ,其中CalendarEventNSManagedObject子类,我将其分类为与事件相关的日期属性分组的字典。 And I have one section for each key of that dictionary in my UITableView (I don't fetch all calendar events at once). UITableView ,该字典的每个键都有一个部分(我不会一次获取所有日历事件)。 However I would like to add more sections to display the date interval gaps between dates with events, using an array of type [[Date]] 但是,我想添加更多部分以使用类型[[Date]]的数组显示带有事件的日期之间的日期间隔差距

  • Clarification: Picture that my calendar app has 2 events stored. 澄清:我的日历应用程序已存储2个事件的图片。 One event 2018-12-05 and one event 2018-12-09, and todays date is 2018-12-01. 一活动2018-12-05和一活动2018-12-09,今天是2018-12-01。 In that case I would like to retrieve an array like the following: [ [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] ] where each of those dates are of type Date of course. 在这种情况下,我想检索如下数组: [ [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当然。 (Which would yield in 4 sections) (这将分四个部分进行)

Question

  • How do I sort/split my arrays to satisfy the format [[Date]] (explained in the "clarification" above)? 如何对数组进行排序/拆分以满足格式[[Date]] (在上面的“说明”中进行了解释)?
    • If there is a simpler way to achieve the same result, that would also be regarded as an answer. 如果有一种更简单的方法来获得相同的结果,那也将被视为答案。

My attempt 我的尝试

I've scaled down to only display the necessary parts. 我已按比例缩小以仅显示必要的部分。

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
   }

Thanks for reading my question. 感谢您阅读我的问题。

In general, using multiple data sources on a single UITableView brings bad luck. 通常,在单个UITableView上使用多个数据源会带来厄运。 .. you might consider changing your data model. ..您可以考虑更改数据模型。

In your example I would consider merging those two data sources in a way that values of dates with no events will be nil , so you would declare it as var dates: [Date: [CalendarEvent]?]? 在您的示例中,我将考虑以没有事件的日期值为nil的方式合并这两个数据源,以便将其声明为var dates: [Date: [CalendarEvent]?]? .

Another way- you would cut off this dictionary and use an array to store objects of type (suggested name) CalendarItem - in there you may store the item's Date and [CalendarEvent]? 另一种方法-您将切断该词典并使用数组存储类型(建议名称) CalendarItem -在其中可以存储项目的Date[CalendarEvent]?

Nevertheless there are many ways to do that and I'm not going to cover them all... 尽管如此,有很多方法可以做到这一点,而我不会覆盖所有这些内容。

If you want to stick with your model, here's a function I've made. 如果您想坚持自己的模型,这是我做的一个功能。 It's probably not the optimal solution and there's some magic that can do it in 4 lines :) but here you go- 这可能不是最佳解决方案,有一些魔术可以在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
    ]
 ]
 */

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM