You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过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机型),可以使用HKDevicemodel属性(返回设备型号代码,如iPhone14,3),再通过型号对照表来判断设备类型。

内容的提问来源于stack exchange,提问作者Si Nguyen

火山引擎 最新活动