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?