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