chore(watchos): logs diagnostics séance (autorisation + erreur HK domaine/code)
Logger os "ch.hypnotruck.coach.watchkitapp/workout" : trace requestAuthorization, statut de partage, startActivity/beginCollection, transitions de session et surtout didFailWithError (domaine+code) pour identifier la cause de l'Error(7). Logger en constante de fichier (Sendable) pour rester accessible aux délégués nonisolated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import HealthKit
|
import HealthKit
|
||||||
|
import os
|
||||||
|
|
||||||
|
private let workoutLog = Logger(subsystem: "ch.hypnotruck.coach.watchkitapp", category: "workout")
|
||||||
|
|
||||||
/// Pilote la séance via HKLiveWorkoutBuilder et pousse les metrics vers l'iPhone.
|
/// Pilote la séance via HKLiveWorkoutBuilder et pousse les metrics vers l'iPhone.
|
||||||
/// `@MainActor` (donc Sendable) : l'état observable vit sur le main ; les callbacks
|
/// `@MainActor` (donc Sendable) : l'état observable vit sur le main ; les callbacks
|
||||||
@@ -39,7 +42,10 @@ final class WorkoutManager: NSObject, ObservableObject {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
try await healthStore.requestAuthorization(toShare: share, read: read)
|
try await healthStore.requestAuthorization(toShare: share, read: read)
|
||||||
|
let woStatus = healthStore.authorizationStatus(for: HKQuantityType.workoutType())
|
||||||
|
workoutLog.info("requestAuthorization OK; workoutType share status=\(woStatus.rawValue)")
|
||||||
} catch {
|
} catch {
|
||||||
|
workoutLog.error("requestAuthorization threw: \(error.localizedDescription)")
|
||||||
statusMessage = "Autorisation Santé refusée : \(error.localizedDescription)"
|
statusMessage = "Autorisation Santé refusée : \(error.localizedDescription)"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -60,12 +66,16 @@ final class WorkoutManager: NSObject, ObservableObject {
|
|||||||
|
|
||||||
let start = Date()
|
let start = Date()
|
||||||
session.startActivity(with: start)
|
session.startActivity(with: start)
|
||||||
|
workoutLog.info("startActivity called, beginning collection…")
|
||||||
try await builder.beginCollection(at: start)
|
try await builder.beginCollection(at: start)
|
||||||
isRunning = true
|
isRunning = true
|
||||||
statusMessage = nil
|
statusMessage = nil
|
||||||
|
workoutLog.info("beginCollection OK, isRunning=true")
|
||||||
} catch {
|
} catch {
|
||||||
self.session = nil
|
self.session = nil
|
||||||
self.builder = nil
|
self.builder = nil
|
||||||
|
let ns = error as NSError
|
||||||
|
workoutLog.error("start failed domain=\(ns.domain) code=\(ns.code): \(error.localizedDescription)")
|
||||||
statusMessage = "Démarrage séance impossible : \(error.localizedDescription)"
|
statusMessage = "Démarrage séance impossible : \(error.localizedDescription)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,6 +148,7 @@ extension WorkoutManager: HKWorkoutSessionDelegate {
|
|||||||
didChangeTo toState: HKWorkoutSessionState,
|
didChangeTo toState: HKWorkoutSessionState,
|
||||||
from fromState: HKWorkoutSessionState,
|
from fromState: HKWorkoutSessionState,
|
||||||
date: Date) {
|
date: Date) {
|
||||||
|
workoutLog.info("session didChangeTo state=\(toState.rawValue) from=\(fromState.rawValue)")
|
||||||
guard toState == .ended else { return }
|
guard toState == .ended else { return }
|
||||||
let builder = workoutSession.associatedWorkoutBuilder()
|
let builder = workoutSession.associatedWorkoutBuilder()
|
||||||
Task {
|
Task {
|
||||||
@@ -154,6 +165,8 @@ extension WorkoutManager: HKWorkoutSessionDelegate {
|
|||||||
nonisolated func workoutSession(_ workoutSession: HKWorkoutSession,
|
nonisolated func workoutSession(_ workoutSession: HKWorkoutSession,
|
||||||
didFailWithError error: Error) {
|
didFailWithError error: Error) {
|
||||||
let message = error.localizedDescription
|
let message = error.localizedDescription
|
||||||
|
let ns = error as NSError
|
||||||
|
workoutLog.error("session didFailWithError domain=\(ns.domain) code=\(ns.code): \(message)")
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
self.statusMessage = "Erreur séance : \(message)"
|
self.statusMessage = "Erreur séance : \(message)"
|
||||||
self.isRunning = false
|
self.isRunning = false
|
||||||
|
|||||||
Reference in New Issue
Block a user