I am creating a workout tracking app and trying to plot the largest weight value on a day over time for a given exercise. The entity "ExerciseSet" contains attributes dateCompleted and weight. There are multiple ExerciseSets saved on the same date, so I want to sort the ExerciseSets descending by weight for each dateCompleted and return the first element (being the max) for each date so that there is one entry (the max) for each date. How can I modify the fetch request to do this? Any suggestions would be greatly appreciated. As of now, there are multiple points for each date when I want just the max weight. My code is here:
import SwiftUI
import Charts
struct ExerciseDetailView: View {
@FetchRequest var exercisesets: FetchedResults<ExerciseSet>
var exercise: String
init(exercise: String) {
self.exercise = exercise
self._exercisesets = FetchRequest(
entity: ExerciseSet.entity(),
sortDescriptors: [NSSortDescriptor(key: "weight", ascending: false)],
predicate: NSPredicate(format: "exercisename == %@", exercise as any CVarArg)
)}
var body: some View {
NavigationView {
ScrollView {
if #available(iOS 16.0, *) {
Chart(exercisesets) { e in
LineMark(x: .value("Date", e.dateCompleted.startOfDay),
y: .value("Reps", e.reps)
)}
}
else {
Text("Oops")
// Fallback on earlier versions
}
}
}
}
}
AFAIK you can't solve this with the
@FetchRequestalone, but you can use a computed var that transforms the fetchedexercisesetsinto a new array that only holds the max weight entries:The technique is commonly used for uniqueValues functions on arrays or other sequences. The
seenDatesset keeps track of dates we already have seen. It's asetand not an array, because a set has a niceinsertbehavior that we can use: if we insert into the set, we get back(inserted: Bool, memberAfterInsert: Set.Element). Soinsertedis true if the element did not exist before, and false if it did.So the
.filterline in the computed var does the magic: it tries to insert the current date intoseenDatesand as the inserted` result is only true for the first time this date was added, those are the elements we are looking for.