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

Most efficient way to bind dates to a Core Data entity

Forums > SwiftUI

I am on my way with creating a habit tracking app which uses Core Data for storing the habits. Because I need to know when I completed a part of my habit, I created a different entity containing only a Date with a many to one relationship to the habit entity. So one habit has a reference to many different dates on which it was completed, and the other way around.

First question: Is this the best method for doing this? Because the longer someone uses the app the more cluttered it gets with dates.

Second question: If it is good, how do I count the times I completed some habit for one specific date or a specific time interval (eg. week). I currently just compactMap over an array and count the result, but when having around 150 items in this array, it gets rather slow:

withAnimation(.easeInOut) {
    let todayCount = habit.dateArray.compactMap { (Calendar.current.isDateInToday($0.date!)) }
    return todayCount.count
}

I currently add a Date like this:

let newhabit = HabitCompletionDate(context: viewContext)
newhabit.date = Date()
newhabit.item = habit

And delete like this:

let habitObject = habit.date?.allObjects.last
viewContext.delete(habitObject as! NSManagedObject)

I don´t need the specific time, only the day of completion would still be enough, but this was the only solution I could come up with.

I have seen someone saying that you could do something like this with an NSPredicate but I did not understand how. As you might have guessed by this rather basic questions, I have no real experience in Core Data and personally it often gives me headaches.

Thanks in advance!

2      

I have seen someone saying that you could do something like this with an NSPredicate but I did not understand how.

You would do something like this:

let cal = Calendar.current

//testDate being the date you want to check for
let startDate = cal.startOfDay(for: testDate)
let endDate = cal.date(byAdding: .day, value: 1, to: startDate)

//assuming date is the name of your Core Data attribute
let predicate = NSPredicate(format: "date >= %@ AND date < %@", startDate, endDate)

3      

Okay, that's a good starting point, thank you! How would I go about implementing it? I know I can use it in a fetch request so that would be useful for my List View, but what should I do when I already have my Habit-item, like I do in my DetailView?

2      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.