天天看點

iOS之HealthKit使用,步數擷取單例1.ZFHealthManager.h2.ZFHealthManager.m

1.ZFHealthManager.h

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, ZFStepAuthorizationStatus) {
    ZFStepAuthorizationStatusNotDetermined = 0,
    ZFStepAuthorizationStatusSharingDenied,
    ZFStepAuthorizationStatusSharingAuthorized,
    ZFStepAuthorizationStatusUnsupport,
};

@interface ZFHealthManager : NSObject

+ (instancetype)sharedManager;


/**
 檢查裝置是否支援健康資料

 @return yes 支援
 */
- (BOOL)isHealthDataAvailable;


/**
 檢查健康資料通路權限

 @return 傳回權限狀态
 */
- (ZFStepAuthorizationStatus)stepAuthorizationStatus;


/**
 請求使用者授權

 @param compltion 回調
 */
- (void)requestHealthKitAuthorization:(void(^)(BOOL success, NSError *error))compltion;


/**
 擷取當天步數

 @param completion 回調   出錯時 value = @"--"
 */
- (void)fetchStepCountToday:(void(^)(NSString *value, NSError *error))completion;

@end
           

2.ZFHealthManager.m

#import "ZFHealthManager.h"
#import <HealthKit/HealthKit.h>

@interface ZFHealthManager ()

@property (nonatomic, strong) HKHealthStore *healthStore;

@end

@implementation ZFHealthManager

static ZFHealthManager *instance = nil;

+ (instancetype)sharedManager {
    if (!instance) {
        instance = [[super allocWithZone:NULL] init];
    }
    return instance;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    return [ZFHealthManager sharedManager];
}

- (ZFStepAuthorizationStatus)stepAuthorizationStatus {
    if (![self isHealthDataAvailable]) { return ZFStepAuthorizationStatusUnsupport; }
    
    ZFStepAuthorizationStatus stepStatus = ZFStepAuthorizationStatusSharingDenied;
    
    HKObjectType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    
    HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:stepType];
    switch (status) {
        case HKAuthorizationStatusNotDetermined:
            stepStatus = ZFStepAuthorizationStatusNotDetermined;
            break;
        case HKAuthorizationStatusSharingDenied:
            stepStatus = ZFStepAuthorizationStatusSharingDenied;
            break;
        case HKAuthorizationStatusSharingAuthorized:
            stepStatus = ZFStepAuthorizationStatusSharingAuthorized;
            break;
        default:
            break;
    }
    return stepStatus;
}

- (void)requestHealthKitAuthorization:(void (^)(BOOL, NSError *))compltion {
    if (![self isHealthDataAvailable]) { return; }
    if ([self stepAuthorizationStatus] != ZFStepAuthorizationStatusNotDetermined) { return; }
    
    HKQuantityType *stepCountType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    NSSet *readTypes = [NSSet setWithObjects:stepCountType,nil];
    
    [self.healthStore requestAuthorizationToShareTypes:readTypes readTypes:readTypes completion:^(BOOL success, NSError * _Nullable error) {
        if (compltion) {
            compltion(success, error);
        }
    }];
}

- (void)fetchStepCountToday:(void (^)(NSString *, NSError *))completion {
    HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:stepType predicate:[self predicateForSamplesToday] limit:HKObjectQueryNoLimit sortDescriptors:@[timeSortDescriptor] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {
        if(error) {
            completion(@"--",error);
        } else {
            double totleSteps = 0;
            for(HKQuantitySample *quantitySample in results) {
                HKQuantity *quantity = quantitySample.quantity;
                HKUnit *heightUnit = [HKUnit countUnit];
                double usersHeight = [quantity doubleValueForUnit:heightUnit];
                totleSteps += usersHeight;
            }
            NSString *result = [NSString stringWithFormat:@"%.0f",totleSteps];
            completion(result,error);
        }
    }];
    [self.healthStore executeQuery:query];
}


- (BOOL)isHealthDataAvailable {
    return [HKHealthStore isHealthDataAvailable];
}

- (HKHealthStore *)healthStore {
    if (!_healthStore) {
        _healthStore = [[HKHealthStore alloc] init];
    }
    return _healthStore;
}


- (NSPredicate *)predicateForSamplesToday {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDate *now = [NSDate date];
    NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:now];
    [components setHour:0];
    [components setMinute:0];
    [components setSecond: 0];
    
    NSDate *startDate = [calendar dateFromComponents:components];
    NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];
    return predicate;
}

- (NSPredicate *)predicateForSamplesYesterday{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDate *now = [NSDate date];
    NSDate *lastDay = [NSDate dateWithTimeInterval:-24*60*60 sinceDate:now];
    NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:lastDay];
    [components setHour:0];
    [components setMinute:0];
    [components setSecond: 0];
    
    NSDate *startDate = [calendar dateFromComponents:components];
    NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];
    return predicate;
}

@end