简体   繁体   中英

iOS Apple HealthKit Apple Watch step data only

Is there a way to get only Apple Watch step data from the HealthKit database. I have worked through examples in Swift 3 and have working code to obtain the merged data which Apple supplies but that contains step data from both the iPhone and Apple Watch.

I have not seen any examples where anyone was able to separate the two pieces of data. Every example I have seen only gives the merged step data. I can iterate over the step data sources but cannot use the source identifier to obtain the step data for a specific calendar time period.

All the Swift 3 code I have seen is along the following lines (Objective-C code follows similar functionality):

    // Request the step count.
    let stepType = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)

    //let predicate = HKQuery.predicateForObjects(from: watchsource)
    let predicate = HKQuery.predicateForSamples(withStart: startdate, end: enddate, options: [])

    // Order doesn't matter, as we are receiving a quantity.

    let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierEndDate, ascending:false)

    // Fetch the steps.
    let query = HKSampleQuery(sampleType:stepType!, predicate: predicate, limit: 0, sortDescriptors:[sortDescriptor]) { query, results, error in
        var steps: Double = 0

        if results != nil {
            if results!.count > 0
            {
                for result in results as! [HKQuantitySample]
                {
                    steps += result.quantity.doubleValue(for: HKUnit.count())
                }
            } // if results
        } // if results != nil

        completion(steps, error as NSError?)
    } // HKSampleQuery()

    healthKitStore.execute(query)

The above code as part of a proper HealthKit authentication works fine and I am able to obtain the step data for any time period.

However, there seems to be no way that HKSampleQuery() or another derivative HealthKit library call can be used for a particular source, ie, Apple Watch data only without the need for having an App on the Apple Watch itself to read the step data.

Yes, I know that one could read the iPhone pedometer data and then subtract that from the total number of steps but pedometer data is kept for only seven days, which is not much use if the time period is say, a month.

Has anyone solved this?

I was having the same issue. I wanted to get a separate step count for iPhone and Apple watch.

here is how I achieved this.

first, we need a predicate for devices to get only the Apple watch results.

let watchPredicate = HKQuery.predicateForObjects(withDeviceProperty: HKDevicePropertyKeyModel, allowedValues: ["Watch"])

now we can query for samples with this predicate and we'll just get the Apple watch entries.

we can also include more predicates to our query, using NSCompoundPredicate

Another approach is to fetch all the samples and then group step count values by the data source ie iPhone, Apple Watch, and third-party apps.

private lazy var store = HKHealthStore()

private func queryStepsCont(startDate: Date,
                            endDate: Date,
                            result: @escaping (Result<[(source: String, count: Int)], Error>) -> Void) {
    guard let type = HKObjectType.quantityType(forIdentifier: .stepCount) else {
        result(.failure(IntegrationsServiceError.preconditionFail))
        return
    }
    let datePredicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate)

    let filteredByDateStepsCountQuery = HKSampleQuery(sampleType: type,
                                                      predicate: datePredicate,
                                                      limit: Int(HKObjectQueryNoLimit),
                                                      sortDescriptors: []) { _, samples, error in
        if let error = error {
            result(.failure(error))
            return
        }
        let sourceNameStepsCount = Dictionary(grouping: samples ?? []) { sample in
            sample.sourceRevision.source.name
        }.map { sourceNameSamples -> (String, Int) in
            let (sourceName, sourceSamples) = sourceNameSamples
            let stepsCount = sourceSamples
                .compactMap { ($0 as? HKQuantitySample)?.quantity.doubleValue(for: .count()) }
                .reduce(0, +)
            return (sourceName, Int(stepsCount))
        }
        result(.success(sourceNameStepsCount))
    }
    store.execute(filteredByDateStepsCountQuery)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM