Implement real-time sync between iOS and Apple Watch apps using WatchConnectivity framework. This replaces reliance on CloudKit which doesn't work reliably in simulators. - Add WatchConnectivityManager to both iOS and Watch targets - Sync workouts, splits, exercises, and logs between devices - Update iOS views to trigger sync on data changes - Add onChange observer to ExerciseView for live progress updates - Configure App Groups for shared container storage - Add Watch app views: WorkoutLogsView, WorkoutLogListView, ExerciseProgressView
84 lines
2.4 KiB
Swift
84 lines
2.4 KiB
Swift
import Foundation
|
|
import CoreData
|
|
|
|
@objc(Workout)
|
|
public class Workout: NSManagedObject, Identifiable {
|
|
@NSManaged public var start: Date
|
|
@NSManaged public var end: Date?
|
|
|
|
@NSManaged public var split: Split?
|
|
@NSManaged public var logs: NSSet?
|
|
|
|
public var id: NSManagedObjectID { objectID }
|
|
|
|
var status: WorkoutStatus {
|
|
get {
|
|
willAccessValue(forKey: "status")
|
|
let raw = primitiveValue(forKey: "status") as? String ?? "notStarted"
|
|
didAccessValue(forKey: "status")
|
|
return WorkoutStatus(rawValue: raw) ?? .notStarted
|
|
}
|
|
set {
|
|
willChangeValue(forKey: "status")
|
|
setPrimitiveValue(newValue.rawValue, forKey: "status")
|
|
didChangeValue(forKey: "status")
|
|
}
|
|
}
|
|
|
|
var label: String {
|
|
if status == .completed, let endDate = end {
|
|
if start.isSameDay(as: endDate) {
|
|
return "\(start.formattedDate())—\(endDate.formattedTime())"
|
|
} else {
|
|
return "\(start.formattedDate())—\(endDate.formattedDate())"
|
|
}
|
|
} else {
|
|
return start.formattedDate()
|
|
}
|
|
}
|
|
|
|
var statusName: String {
|
|
return status.displayName
|
|
}
|
|
}
|
|
|
|
// MARK: - Convenience Accessors
|
|
|
|
extension Workout {
|
|
var logsArray: [WorkoutLog] {
|
|
let set = logs as? Set<WorkoutLog> ?? []
|
|
return set.sorted { $0.order < $1.order }
|
|
}
|
|
|
|
func addToLogs(_ log: WorkoutLog) {
|
|
let items = mutableSetValue(forKey: "logs")
|
|
items.add(log)
|
|
}
|
|
|
|
func removeFromLogs(_ log: WorkoutLog) {
|
|
let items = mutableSetValue(forKey: "logs")
|
|
items.remove(log)
|
|
}
|
|
}
|
|
|
|
// MARK: - Fetch Request
|
|
|
|
extension Workout {
|
|
@nonobjc public class func fetchRequest() -> NSFetchRequest<Workout> {
|
|
return NSFetchRequest<Workout>(entityName: "Workout")
|
|
}
|
|
|
|
static func recentFetchRequest() -> NSFetchRequest<Workout> {
|
|
let request = fetchRequest()
|
|
request.sortDescriptors = [NSSortDescriptor(keyPath: \Workout.start, ascending: false)]
|
|
return request
|
|
}
|
|
|
|
static func fetchRequest(for split: Split) -> NSFetchRequest<Workout> {
|
|
let request = fetchRequest()
|
|
request.predicate = NSPredicate(format: "split == %@", split)
|
|
request.sortDescriptors = [NSSortDescriptor(keyPath: \Workout.start, ascending: false)]
|
|
return request
|
|
}
|
|
}
|