Search code examples
objective-cswiftxcodereact-nativehealthkit

query not working - React Native app + Xcode


My HealthKit query is not working.
I am trying to get the steps count and I am confused on which part of my code is in-correct.
When I build the app, it either throws "updateStepsCount is not a recognised objc method" or "Unhandled promise rejection".
Where am I going wrong here!!!

Controller.swift:

@objc
  func updateStepsCount(_ statisticsCollection: HKStatisticsCollection, _ resolve: @escaping RCTPromiseResolveBlock,
                        rejecter reject: @escaping (RCTPromiseRejectBlock) -> Void) {
      
      let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
      
      let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date())
      
      let anchorDate = Date.mondayAt12AM()
      
      let daily = DateComponents(day: 1)
      
      let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictStartDate)
      
      let query = HKStatisticsCollectionQuery(quantityType: stepType, quantitySamplePredicate: predicate, options: .cumulativeSum, anchorDate: anchorDate, intervalComponents: daily)

          healthStore.execute(query)
    
    struct Step {
        let id = UUID()
      var count: Int?
        var date: Date?
    }
      let endDate = Date()
      
    statisticsCollection.enumerateStatistics(from: startDate!, to: endDate) { (statistics, stop) in
          
          let count = statistics.sumQuantity()?.doubleValue(for: .count())
          let steps = Int(count ?? 0)
        
        var stepCount = [Step]()
        var tempStepCount = Step(count: steps, date: Date())
          
        tempStepCount.count = steps
        tempStepCount.date = startDate
        stepCount.append(tempStepCount)
      }
    resolve(Step())
  }


Controller.m

RCT_EXTERN_METHOD(updateStepsCount: (HKStatisticsCollection)someStatisticsCollection
                  resolve: (RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)

JS side:

 clickHandler = async() => {
    const login = HealthkitController.updateStepsCount()
    .then(result => console.warn(result));
  }

Solution

  • Thats because your updateStepsCount method requires argument statisticsCollection as a first param. When you try to call updateStepsCount() in js it converts to updateStepsCount in objc bridge but you don't have this method you have updateStepsCount: and this one has a param so you have to pass a param.

    NOTE: React Native bridge works only with standard JSON types so input parameters can be standard types (number, string, dictionary etc.) but you can also use RCTConvert to map they to custom ones. Result of your promise must be standard type as well so you can not return your struct. (https://reactnative.dev/docs/native-modules-ios#argument-types)