如何通过HealthKit获取Health app源标签页的iPhone/Apple Watch设备类型信息?
我明白你的痛点——HKSource确实没直接提供设备类型的属性,不过我们有两种可靠的方式来区分iPhone和Apple Watch对应的源,帮你解决这个问题:
方法1:通过HKSource的bundleIdentifier识别
苹果官方的健康数据来源有固定的bundle标识规律,我们可以直接通过这个来判断:
- iPhone本地生成的健康数据,对应的源bundleIdentifier通常是
com.apple.Health - Apple Watch同步过来的数据,源的bundleIdentifier一般会带有Watch相关标识,比如
com.apple.Health.Watch(不同iOS/watchOS版本可能略有后缀差异,但核心特征不变)
你可以修改你的HKSourceQuery代码来实现识别:
let sampleType = HKObjectType.quantityType(forIdentifier: .stepCount)! let healthStore = HKHealthStore() let query = HKSourceQuery(sampleType: sampleType, samplePredicate: nil) { query, sources, error in guard let sources = sources else { // 处理错误逻辑 print("获取源失败:\(error?.localizedDescription ?? "未知错误")") return } for source in sources { let bundleId = source.bundleIdentifier switch bundleId { case "com.apple.Health": print("✅ 该源对应iPhone:\(source.name)") case let id where id.contains("Watch") || id.hasSuffix(".Watch"): print("⌚ 该源对应Apple Watch:\(source.name)") default: print("🔵 其他第三方源:\(source.name)(Bundle ID:\(bundleId))") } } } healthStore.execute(query)
方法2:通过样本的HKDevice信息精准关联
如果担心bundleIdentifier的规律随系统版本变化,我们可以直接从健康样本中提取设备信息,再关联到对应的源——这种方式更精准,适合对兼容性要求高的场景:
let healthStore = HKHealthStore() let stepCountType = HKObjectType.quantityType(forIdentifier: .stepCount)! // 创建样本查询,获取包含设备信息的健康数据 let sampleQuery = HKSampleQuery( sampleType: stepCountType, predicate: nil, limit: HKObjectQueryNoLimit, sortDescriptors: nil ) { query, samples, error in guard let quantitySamples = samples as? [HKQuantitySample] else { print("获取样本失败:\(error?.localizedDescription ?? "未知错误")") return } // 构建「源-设备类型」的映射表 var sourceToDeviceMap = [HKSource: String]() for sample in quantitySamples { guard let source = sample.source, let device = sample.device else { continue } // 识别设备类型:可以用localizedModel(本地化名称)或model(型号代码) let deviceType: String if device.localizedModel == "iPhone" { deviceType = "iPhone" } else if device.localizedModel == "Apple Watch" { deviceType = "Apple Watch" } else { deviceType = device.localizedModel ?? "未知设备" } // 避免重复赋值,只保留第一次识别的结果 if sourceToDeviceMap[source] == nil { sourceToDeviceMap[source] = deviceType } } // 输出最终的源与设备对应关系 for (source, deviceType) in sourceToDeviceMap { print("源名称:\(source.name),对应设备:\(deviceType)") } } healthStore.execute(sampleQuery)
额外注意事项
- 无论用哪种方法,都要确保你已经在
Info.plist中配置了HealthKit权限描述,并且向用户请求了对应的读写权限,否则无法获取任何源或样本数据。 - 如果需要更通用的设备型号识别(比如区分不同iPhone机型),可以使用
HKDevice的model属性(返回设备型号代码,如iPhone14,3),再通过型号对照表来判断设备类型。
内容的提问来源于stack exchange,提问作者Si Nguyen




