Sung-jun Kim
Sung-jun Kim

Reputation: 41

How to get walking and running distance using HealthKit in swift

I'm making Health App. I want to get walkingRunningDistance from HealthKit in Swift. But, I have a problem. Return value is 0.0mile.

Why return value is 0 mile?

My code is this.

func recentSteps3(completion: (Double, NSError?) -> () ){
    let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)

    let date = NSDate()

    let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!

    let newDate = cal.startOfDayForDate(date)

    let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: HKQueryOptions.StrictStartDate)

    let query = HKSampleQuery(sampleType: type!, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { query, results, error in

        var distance: Double = 0

        if results?.count > 0
        {
            for result in results as! [HKQuantitySample]
            {
                distance += result.quantity.doubleValueForUnit(HKUnit.mileUnit())
            }
        }

        completion(distance, error)
    }

    healthAuth.healthStore.executeQuery(query)
}

Upvotes: 4

Views: 11743

Answers (4)

Makwin Santhosh K
Makwin Santhosh K

Reputation: 1

if it return zero then your code is correct. but since it is in simulator view, simulator you cannot read Distance. for that go to Health App in your simulator and select Distance Walking Running Distance and press add data

and then your app might read those data.

Upvotes: 0

KZD76
KZD76

Reputation: 122

For Swift 4.1

After enabled the HealthKit in your project's capabilities and added the necessary "Privacy - Health Share Usage Description" key to your info.plist file...

Ensure you are requesting for the approval of the user by adding this to the ViewController.swift, practically in the viewDidLoad() function.

    let store = HKHealthStore()

    let stepType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
    let woType = HKObjectType.workoutType()

    store.requestAuthorization(toShare: [], read: [stepType, woType], completion: { (isSuccess, error) in
        if isSuccess {
            print("Working")
            self.getSteps()
        } else {
            print("Not working")
        }
    })

Then create the getSteps() function.

func getSteps() {
    let startDate = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date())!

    let endDate = Date()

    print("Collecting workouts between \(startDate) and \(endDate)")

    let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: HKQueryOptions.strictEndDate)

    let query = HKSampleQuery(sampleType: HKQuantityType.quantityType(forIdentifier: .distanceWalkingRunning)!, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { (query, results, error) in
        for item in results! {
            print(item)
        }
    }

    store.execute(query)
}

Upvotes: 3

Carien van Zyl
Carien van Zyl

Reputation: 2873

Your code will return a value if

  1. You have requested permission from the user to read distanceWalkingRunning from HealthKit
  2. The user has granted your app permission.

If not, your code will return 0.

To request authorization, you can call

func requestAuthorization(toShare typesToShare: Set<HKSampleType>?, read typesToRead: Set<HKObjectType>?, completion: @escaping (Bool, Error?) -> Swift.Void)

where typesToRead contains

let distanceType =  HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier.distanceWalkingRunning)!

I believe that using a HKStatisticsQuery or HKStatisticsCollectionQuery will be more efficient. Here is an example.

guard let type = HKSampleType.quantityType(forIdentifier: .distanceWalkingRunning) else {
    fatalError("Something went wrong retriebing quantity type distanceWalkingRunning")
}
let date =  Date()
let cal = Calendar(identifier: Calendar.Identifier.gregorian)
let newDate = cal.startOfDay(for: date)

let predicate = HKQuery.predicateForSamples(withStart: newDate, end: Date(), options: .strictStartDate)

let query = HKStatisticsQuery(quantityType: type, quantitySamplePredicate: predicate, options: [.cumulativeSum]) { (query, statistics, error) in        
    var value: Double = 0

    if error != nil {
        print("something went wrong")
    } else if let quantity = statistics?.sumQuantity() {
        value = quantity.doubleValue(for: HKUnit.mile())
    }
    DispatchQueue.main.async {
        completion(value)
    }
}
healthStore.execute(query)

Upvotes: 7

gireesh Chanti
gireesh Chanti

Reputation: 84

healthStore =[HKHealthStore new];
HKQuantityType *stepType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKSampleType *sleepType = [HKSampleType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis];
HKQuantityType *walkType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
NSArray *arrayType = @[stepType,sleepType,walkType];

[healthStore requestAuthorizationToShareTypes:[NSSet setWithArray:arrayType]
                                    readTypes:[NSSet setWithArray:arrayType] completion:^(BOOL succeeded, NSError *error) {
                                        if (succeeded) {
                                            NSLog(@"Not working");
                                            NSLog(@"error %@",error);
                                        } else {
                                            NSLog(@"Working!");
                                            NSLog(@"error %@",error);
                                        }
                                        [self getStepCount];
                                    }];

The above method for requsting access and below method to get count

-(void)getStepCount{
     NSInteger limit = 0;
     NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd hh:mm:ss"];
    NSDate *startDate = [NSDate  dateWithTimeIntervalSince1970:1372418789];
    // Divided by 1000 (i.e. removed three trailing zeros) ^^^^^^^^
    NSString *formattedDateString = [dateFormatter stringFromDate:startDate];
   // Fri, 28 Jun 2013 11:26:29 GMT
   NSLog(@"start Date: %@", formattedDateString);
   NSDateFormatter *dateFormatter1=[[NSDateFormatter alloc] init];
   [dateFormatter1 setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
   NSLog(@"%@",[dateFormatter1 stringFromDate:[NSDate date]]);
   NSString *dateString =[dateFormatter1 stringFromDate:[NSDate date]];
  NSDate *endDate = [dateFormatter1 dateFromString:dateString];


 NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictEndDate];

HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]
                        predicate: predicate
                        limit: limit
                        sortDescriptors: nil
                        resultsHandler:^(HKSampleQuery *query, NSArray* results, NSError *error){
                            dispatch_async(dispatch_get_main_queue(), ^{
                                // sends the data using HTTP
                                int dailyAVG = 0;
                                NSLog(@"result : %@",results);
                                for(HKQuantitySample *samples in results)
                                {
                                    NSLog(@"dailyAVG : %@",samples);
                                }
                                NSLog(@"dailyAVG : %d",dailyAVG);

                                NSLog(@"%@",@"Done");
                            });
                        }];
[healthStore executeQuery:query];

}

Upvotes: 0

Related Questions