Reputation: 175
I am trying create a lookup if there is any workout registered on a specific date.
The Object class looks like this:
class Workout: Object {
@objc dynamic var date: Date?
// List of exercises (to-many relationship)
var exercises = List<Exercise>()
}
And
class Exercise: Object {
@objc dynamic var name: String?
// List of sets (to-many relationship)
var sets = List<Set>()
var parentWorkout = LinkingObjects(fromType: Workout.self, property: "exercises")
}
In Realm, I can see that there is one registered with the date 2019-12-07 19:48:35 +0000;
. So I am adding a check in my viewDidLoad
like this:
let nowDate = Date()
func checkIfWorkoutHasBeenRegistered() {// Check if there already exist a workout today
let realm = try! Realm()
let todaysWorkouts = realm.objects(Workout.self).filter("date = %@", nowDate)
if todaysWorkouts.isEmpty {
print("No workout found")
} else {
print("Workout has been created")
}
}
But it gives me output No workout found
, even thought I have registered a workout today. Any tips?
Upvotes: 0
Views: 1517
Reputation: 35657
This may or may not be applicable but there is some complexity in working with a Date object in its pure form.
As shown in your question for example, what if you want to get a workout for 12/09/2019? Or, get ALL workouts on a date. If you generate a date object for the date you want to filter for like this
var dateComps = DateComponents()
dateComps.day = 08
dateComps.month = 12
dateComps.year = 2019
let cal = Calendar.current
let theDate = cal.date(from: dateComps)
there's also a time component to factor in so this will query will not work
let workoutResults = realm.objects(Workout.self).filter("timestamp == %d", theDate)
because the date object stored in Realm is this
2019-12-08T15:32:40
and your query is for this
2019-12-08T05:00:00
note that even though the DAY is the same the TIME is different so no match. You could craft a range filter for any results between 12AM and 11:59 PM but again, may be overly complex.
It comes down to if you need the time portion of the date. If not, how about this model
class Workout: Object {
@objc dynamic var workout_id = UUID().uuidString
@objc dynamic var date_stamp: String?
@objc dynamic var workout_name: String?
@objc dynamic var timestamp: Date?
convenience init(withName: String) {
self.init()
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMdd"
let result = formatter.string(from: date)
self.date_stamp = result
self.workout_name = withName
self.timestamp = date
}
var exercises = List<Exercise>()
override static func primaryKey() -> String? {
return "workout_id"
}
}
and you get the best of both as your workout now has a name, a searchable and sortable date string and an actual time stamp if needed.
name: "Monday Workout"
date_stamp: "20191208"
timestamp: 2019-12-08T15:32:40
So the filter for a particular date becomes
let workoutResults = realm.objects(Workout.self).filter("date_stamp == '20191208'")
Upvotes: 0
Reputation: 15331
With your current predicate you're comparing the save date and time to current date and time which are certainly going to be different because even a fraction of a second difference is going to make them unequal. Instead you likely want to see if the saved date falls within a some range. For example, if you wanted to see all objects that have a date
that occurred "today," you could create a predicate like:
let startOfDay = Calendar.current.startOfDay(for: Date())
let endOfDay = Calendar.current.date(byAdding: .day, value: 1, to: startOfDay) ?? Date()
let predicate = NSPredicate(format: "date >= %@ && date < %@", startOfDay as NSDate, endOfDay as NSDate)
let todaysWorkouts = realm.objects(Workout.self).filter(predicate)
Upvotes: 2