mycode/myApp/Keging/IOS/HealthRecorder.swift
songyc macbook 9c9df03571 polish(keging): 메인·운동 화면 그래픽 강화 + 도움말 취소선(마크다운 ~) 수정
- 메인: 텍스트 한 줄 요약 → 수축·이완·횟수 카드 3장(아이콘+큰 숫자, 탭=세팅)
- 운동 화면: 국면 색 전환(수축=그린·이완=앰버, 카운터 색 연동) + 세트 진행 링 +
  큰 현재 횟수 카운터(numericText 전환)
- 도움말 취소선 원인 = SwiftUI Text 마크다운의 ~쌍 해석 — 사용자 문구의 ASCII ~를
  전각 ~로 전면 교체(4곳), CLAUDE.md에 금지 규칙 기록
- 신규 QA 인자 -noHealth(권한 시트가 캡처 가리는 것 방지)
- 검증: Debug·Release 빌드 그린, 화면 QA(메인 카드·수축/이완 국면·도움말), 카탈로그 0/0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPmp29DQHY6Ahfss5SRopT
2026-08-29 20:49:30 +09:00

58 lines
2.4 KiB
Swift

//
// HealthRecorder.swift
// Keging
//
// '' (iOS ).
// (workout effort score, 1~10) .
// · · .
//
import HealthKit
@MainActor
final class HealthRecorder {
static let shared = HealthRecorder()
private let store = HKHealthStore()
private var authRequested = false
private init() {}
private static var shareTypes: Set<HKSampleType> {
[HKObjectType.workoutType(), HKQuantityType(.workoutEffortScore)]
}
/// ( )
func requestAuthorizationIfNeeded() {
#if DEBUG
// QA
if CommandLine.arguments.contains("-noHealth") { return }
#endif
guard HKHealthStore.isHealthDataAvailable(), !authRequested else { return }
authRequested = true
store.requestAuthorization(toShare: Self.shareTypes, read: nil) { _, _ in }
}
/// , (/ )
func save(record: SessionRecord, effortScore: Int, workoutType: HealthWorkoutType) {
guard HKHealthStore.isHealthDataAvailable() else { return }
let start = record.startedAt
let end = start.addingTimeInterval(Double(record.reps * (record.contractSeconds + record.relaxSeconds)))
let configuration = HKWorkoutConfiguration()
configuration.activityType = workoutType.activityType
let builder = HKWorkoutBuilder(healthStore: store, configuration: configuration, device: .local())
Task { @MainActor in
do {
try await HealthKitCalls.beginCollection(builder, at: start)
try await HealthKitCalls.endCollection(builder, at: end)
let workout = try await HealthKitCalls.finishWorkout(builder)
if effortScore > 0, let workout {
try? await HealthKitCalls.relateEffort(store: store, workout: workout, score: effortScore)
}
} catch {
//
}
}
}
}