Xcode 16.4无法识别iOS HealthKit的HKWorkoutPlan、HKWorkoutComposition等API的问题求助
Xcode 16.4无法识别iOS HealthKit的HKWorkoutPlan、HKWorkoutComposition等API的问题求助
各位好,我最近在开发一个需要和HealthKit交互的iOS应用,遇到了一个很头疼的问题:使用Xcode 16.4(版本号16F6)编译代码时,编译器一直报找不到HealthKit相关API的错误,具体报错如下:
Cannot find 'HKWorkoutPlan' in scopeCannot find 'HKWorkoutComposition' in scopeCannot find type 'HKWorkoutGoal' in scope
我的部署目标是iOS 17,代码里也给用到这些API的方法加上了@available(iOS 17.0, *)的注解,按道理这些API在iOS 17及以上版本是原生支持的,但Xcode就是识别不到它们。
下面是我的HealthKitManager.swift完整代码,报错的部分集中在saveWorkoutPlan方法里:
// // HealthKitManager.swift // AppHere // import Foundation import HealthKit class HealthKitManager { // MARK: - Properties // Create a singleton instance so the whole app can share it. static let shared = HealthKitManager() let healthStore = HKHealthStore() // Private init to enforce the singleton pattern. private init() {} // MARK: - Authorization func requestAuthorization(completion: @escaping (Bool, Error?) -> Void) { // First, gotta make sure HealthKit is actually available on this device. guard HKHealthStore.isHealthDataAvailable() else { completion(false, HealthKitError.notAvailableOnDevice) return } // These are the data types I'll be writing to HealthKit. let typesToShare: Set = [ HKObjectType.workoutType() ] // I don't need to read any data right now, but I'm requesting permission anyway // so I don't have to ask the user again later if I add read features. let typesToRead: Set = [ HKObjectType.workoutType() ] // Now, actually ask the user for permission. healthStore.requestAuthorization(toShare: typesToShare, read: typesToRead) { success, error in // This completion can come back on a background thread, so I need to make // sure I dispatch to the main queue before calling the completion handler. DispatchQueue.main.async { completion(success, error) } } } // MARK: - Workout Plan Management // Even though my deployment target is iOS 17, using @available makes the code's // requirements clearer and prevents accidental use if the target ever changes. @available(iOS 17.0, *) func saveWorkoutPlan(_ workout: StructuredWorkout, completion: @escaping (Bool, Error?) -> Void) { do { // Set up the basic configuration for this workout. let workoutConfiguration = HKWorkoutConfiguration() workoutConfiguration.activityType = workout.discipline workoutConfiguration.locationType = .outdoor // Assuming outdoor for now. var finalBlocks: [HKWorkoutComposition.Block] = [] var blockBuffer: [HKWorkoutComposition.Block] = [] for step in workout.steps { if step.type == .repeatStep { // If this is a repeat step, I need to wrap everything in the buffer // into a repeating block. guard !blockBuffer.isEmpty, let repeatCount = step.repeatCount else { continue } // Create a composition from the buffered steps that need to be repeated. let repeatComposition = try HKWorkoutComposition(blocks: blockBuffer) let repeatBlock = try HKWorkoutComposition.Block(composition: repeatComposition, repetitions: repeatCount) finalBlocks.append(repeatBlock) // Clear out the buffer so it's ready for the next set of steps. blockBuffer.removeAll() } else { // For a regular step, just create a single block and add it to the buffer. let goal = workoutGoal(for: step) let block = try HKWorkoutComposition.Block(activity: workoutConfiguration, goal: goal) blockBuffer.append(block) } } // After the loop, I need to add any steps left in the buffer that weren't // part of a final repeat block. if !blockBuffer.isEmpty { finalBlocks.append(contentsOf: blockBuffer) } // Build the final composition from all the blocks I've created. let composition = try HKWorkoutComposition(blocks: finalBlocks) let plan = HKWorkoutPlan(name: workout.name, composition: composition, date: workout.date) healthStore.save(plan) { success, error in if success { print("✅ Successfully saved workout plan: \(workout.name)") } // Make sure to call the completion handler on the main thread. DispatchQueue.main.async { completion(success, error) } } } catch { // Catch any errors that happen during the block/composition creation. print(" Failed to build workout plan composition: \(error.localizedDescription)") completion(false, error) } } // Helper function to turn my WorkoutStep into a HealthKit goal. @available(iOS 17.0, *) private func workoutGoal(for step: WorkoutStep) -> HKWorkoutGoal { switch step.target { case .open: return .init(duration: step.duration) case .power(let low, let high): let lowPower = HKQuantity(unit: .watt(), doubleValue: low) let highPower = HKQuantity(unit: .watt(), doubleValue: high) return .init(powerRangeFrom: lowPower, to: highPower, for: step.duration) case .pace(let low, let high): // Important: HealthKit expects speed (m/s), not pace (min/mile). // I'm handling the conversion before this function is ever called. let lowSpeed = HKQuantity(unit: .meter().unitDivided(by: .second()), doubleValue: low) let highSpeed = HKQuantity(unit: .meter().unitDivided(by: .second()), doubleValue: high) return .init(speedRangeFrom: lowSpeed, to: highSpeed, for: step.duration) case .heartRate(let low, let high): let bpmUnit = HKUnit.count().unitDivided(by: .minute()) let lowHR = HKQuantity(unit: bpmUnit, doubleValue: low) let highHR = HKQuantity(unit: bpmUnit, doubleValue: high) return .init(heartRateRangeFrom: lowHR, to: highHR, for: step.duration) } } } // 自定义错误枚举,用于HealthKit相关错误处理 enum HealthKitError: Error { case notAvailableOnDevice }
我已经尝试过这些方案,但都没能解决问题:
- 确认项目的部署目标确实是iOS 17.0,没有设置成更低版本
- 代码里已经正确导入了
HealthKit框架 - 清理了Xcode的构建缓存(Cmd+Shift+K),还手动删除了Derived Data文件夹
- 重启过Xcode和电脑,但报错依然存在
有没有朋友遇到过类似的问题?或者知道怎么让Xcode正确识别这些HealthKit API?麻烦给我点思路,非常感谢!
内容来源于stack exchange
相关产品推荐
相关产品推荐

