UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

How to I save a recurring meeting in Core Data ?

Forums > SwiftUI

Hi guys,

I hope you are all well?

I have a question about events that happens every week on a set day

I have a app where I am using Core Data, now everything saves and I can retrieve that data from Core Data no problem.

The issue I have is this:

When I create a meeting event in my app it saves to Core Data on the date specified, however that event must happen every 7 days on repeat, ie if a event is saved for a Monday it must be listed on every Monday when scrolling to that specific day

DateHolder object:

`import CoreData import SwiftUI

class DateHolder: ObservableObject {

@Published var date = Date()
@Published var selectedMeetings: [Meeting] = []

let calendar: Calendar = Calendar.current

init(_ context: NSManagedObjectContext) {
    refreshedMeetingItems(context)
}

func moveDate(days: Int,_ context: NSManagedObjectContext) {
    date = calendar.date(byAdding: .day, value: days, to: date)!

}

func weeklyDate(days: Int,_ context: NSManagedObjectContext) {
    date = calendar.date(byAdding: .day, value: days, to: date)!
}

 func refreshedMeetingItems(_ context: NSManagedObjectContext) {
    selectedMeetings = fetchMeetingItem(context)
}

func fetchMeetingItem(_ context: NSManagedObjectContext) -> [Meeting] {
    do {
        return try context.fetch(dailyFetch()) as [Meeting]
    }
    catch let error {
        fatalError("Unresolved error \(error)")

    }
}

func dailyFetch() -> NSFetchRequest<Meeting> {
    let request = Meeting.fetchRequest()

    request.sortDescriptors = sortOrder()
    request.predicate = predicate()
    return request
}

private func sortOrder() -> [NSSortDescriptor] {
    let daySort = NSSortDescriptor(keyPath: \Meeting.meetingDay, ascending: true)
    let timeSort = NSSortDescriptor(keyPath: \Meeting.meetingTime, ascending: true)
    let favouriteSort = NSSortDescriptor(keyPath: \Meeting.isFavourite, ascending: true)

    return [daySort, timeSort, favouriteSort]
}

private func predicate() -> NSPredicate {
    let start = calendar.startOfDay(for: date)
    let end = calendar.date(byAdding: .day, value: 1, to: start)

    return NSPredicate(format: "meetingDay >= %@ AND meetingDay <= %@", start as NSDate, end! as NSDate)
}

}

Date Scoller View:

import SwiftUI

struct DateScroller: View { @EnvironmentObject var dateHolder: DateHolder @Environment(.managedObjectContext) var viewContext

var body: some View {
    HStack{
        Spacer()
        Button(action: moveBack){
            Image(systemName: "arrow.left")
                .imageScale(.medium)
        }

        Text(dateFormatted())
            .font(.title)
            .animation(.none)
            .frame(maxWidth: .infinity)

        Button(action: moveForward) {
            Image(systemName: "arrow.right")
                .imageScale(.medium)
        }
    }
}

func moveBack() {
    withAnimation {
        dateHolder.moveDate(days: -1, viewContext)
        dateHolder.refreshedMeetingItems(viewContext)
    }

}

func moveForward() {
    withAnimation {
        dateHolder.moveDate(days: +1, viewContext)
        dateHolder.refreshedMeetingItems(viewContext)
    }
}

func dateFormatted() -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd LLL YYYY"
    return dateFormatter.string(from: dateHolder.date)
}

}

struct DateScroller_Previews: PreviewProvider { static var previews: some View { DateScroller() } }

Add meeting view:

import SwiftUI

struct AddMeetingView: View {

@Environment(\.managedObjectContext) var viewContext
@Environment(\.dismiss) var dismiss
@EnvironmentObject var dateHolder: DateHolder

@State var meeting: Meeting?
@State   var name:String
@State   var type:String
@State   var meetingTime:Date
@State   var meetingDay:Date
@State   var address:String
@State   var detail:String
@State var isWeekly = true

var body: some View {
    NavigationView{
        Form {
            Section(content: {
                FormTextField(label: "NAME", placeholder: "Fill in the meeting name", value: $name)
                FormTextField(label:"Meeting Type",placeholder: "Meeting Type", value: $type)
                DatePicker("When", selection: $meetingDay, displayedComponents: displayComp())
                Toggle("Weekly", isOn: $isWeekly)
                FormTextField(label: "Address",placeholder: "Fill in the meeting address", value: $address)
                FormTextField(label:"About",placeholder: "Meeting information", value: $detail)

            }, header: {
                Text("Meeting Details")
            })
        }

        //}
        .navigationTitle("Add Meeting")
        .toolbar{
            ToolbarItem(placement: .navigationBarLeading) {
                Button(action: {
                    dismiss()
                }) {
                    Image(systemName: "xmark")
                        .foregroundColor(.accentColor)
                }
            }
            ToolbarItem {
                Button {
                    dismissKeyboard()
                } label: {
                    Image(systemName: "keyboard.chevron.compact.down")
                }

            }
            ToolbarItem(placement: .navigationBarTrailing) {
                Button(action: {

                    save()
                    dismiss()
                }) {
                    Image(systemName: "square.and.arrow.down")
                        .foregroundColor(.accentColor)
                }
            }

        }

    }
    .onAppear{
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            meetingDay = dateHolder.date
        }
    }
}

private func save() {
     meeting = Meeting(context: viewContext)

    meeting?.name         = name
    meeting?.type         = type
    meeting?.address      = address
    meeting?.meetingDay   = meetingDay
    meeting?.meetingTime  = meetingTime
    meeting?.detail       = detail
    meeting?.isFavourite  = false
    meeting?.isWeekly = isWeekly

    do {
        dateHolder.weeklyDate(days: 0, viewContext)
        try viewContext.save()
    } catch {
        print("Failed to save meeting")
        print(error.localizedDescription)
    }
}

func displayComp() -> DatePickerComponents {
    return isWeekly ? [.hourAndMinute, .date] : [.date]
}

How should I update the save function to ensure that the event is saved every 7 days?

2      

One idea for a recurring meeting per weekday is to save a start and a end date. Check for the weekday instead of the date itself. One way or the other I think you have to adapt your Meeting class.

2      

@Pauli: Please edit your original message and place ALL code inside the markup. You have some errors in your markup and there is code outside where it should be.

Thanks.

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.