Search code examples
arraysswiftmodel

Swift - How do I add a new object to an array inside another object that has a grouping field


I have an array of events of type.

struct Event { var id: UUID, var title: String, var date: Date } 

this array is inside another object with an occurrence title

struct Category { var occurs: String, var events: [Event] }

occurs defines if the event.date is before or after Now(), so that i can make Section Headers in a table to show Past and Upcoming sections.

I am only persisting Event(need id for Notification changes).

I am able to save and load data into an array of Category but how do I add a new event and get it into the correct "occurs" array.

Data Example (Event struc has init that assigns the UUID to id. )

    [
        Category(occurs: "passed", events: [
            Event(title: "Yesterday", date: Calendar.current.date(byAdding: .day, value: -1, to: Date())!)
        ]),
        Category(occurs: "upcoming", events: [
            Event(title: "Tomorrow", date: Calendar.current.date(byAdding: .day, value: 1, to: Date())!),
            Event(title: "Future", date: Calendar.current.date(byAdding: .day, value: 5, to: Date())!)
        ])
    ]

Category array is then consumed by a List/ForEach to spit out the Section and Body.

Thanks


Solution

  • First you need a way to figure out if the event has passed or is upcoming. You could add an extension to your Event struct to compute this:

    extension Event {
        var occurs: String {
            let diff = date.timeIntervalSince1970 - Date().timeIntervalSince1970
            return diff >= 0 ? "upcoming" : "passed"
        }
    }
    

    Next you need to find the index of the category that matches the event's occurs value in your data array. You can do this by using the firstIndex method:

    let newEvent = Event(
        title: "2 hours from now",
        date: Calendar.current.date(byAdding: .hour, value: 2, to: Date())!)
    
    let newEventOccurs = newEvent.occurs
    
    if let index = data.firstIndex(where: { $0.occurs == newEventOccurs }) {
        data[index].events.append(newEvent)
    }
    

    Notice we use an if-let binding because it's possible you don't have a category in your array for the event. In this case, you will want to add the category to your array with the new event.