-
-
Save Ushio/cf5be41a2b0f52112240ff05c6f84fc0 to your computer and use it in GitHub Desktop.
HKLiveWorkoutBuilder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "InterfaceController.h" | |
@interface InterfaceController () | |
@property (weak, nonatomic) IBOutlet WKInterfaceLabel *stateLabel; | |
@property (weak, nonatomic) IBOutlet WKInterfaceButton *startButton; | |
@property (weak, nonatomic) IBOutlet WKInterfaceButton *stopButton; | |
@property (weak, nonatomic) IBOutlet WKInterfaceLabel *heartrateLabel; | |
@end | |
@implementation InterfaceController { | |
HKHealthStore *_healthStore; | |
HKWorkoutConfiguration *_workoutConfig; | |
HKWorkoutSession *_session; | |
HKLiveWorkoutBuilder *_builder; | |
} | |
- (void)awakeWithContext:(id)context { | |
[super awakeWithContext:context]; | |
_healthStore = [[HKHealthStore alloc] init]; | |
// Read: HeartRate | |
NSMutableArray<HKObjectType *> *readTypeArray = [[NSMutableArray<HKObjectType *> alloc] init]; | |
[readTypeArray addObject: [HKQuantityType quantityTypeForIdentifier: HKQuantityTypeIdentifierHeartRate]]; | |
NSSet<HKObjectType *> *readTypes = [NSSet<HKObjectType *> setWithArray: readTypeArray]; | |
// Share: Workout | |
NSMutableArray<HKSampleType *> *shareTypeArray = [[NSMutableArray<HKSampleType *> alloc] init]; | |
[shareTypeArray addObject: [HKSampleType workoutType]]; | |
NSSet<HKSampleType *> *shareTypes = [NSSet<HKSampleType *> setWithArray: shareTypeArray]; | |
[_healthStore requestAuthorizationToShareTypes: shareTypes readTypes: readTypes completion: ^(BOOL success, NSError * _Nullable error) { | |
if(success == NO) { | |
NSLog(@"requestAuthorizationToShareTypes failed."); | |
NSLog(@"%@", error); | |
} else { | |
NSLog(@"requestAuthorizationToShareTypes succeeded."); | |
dispatch_async(dispatch_get_main_queue(), ^{ | |
[self setupWorkout]; | |
}); | |
} | |
}]; | |
} | |
- (void)setupWorkout { | |
_workoutConfig = [[HKWorkoutConfiguration alloc] init]; | |
_workoutConfig.activityType = HKWorkoutActivityTypeRunning; | |
_workoutConfig.locationType = HKWorkoutSessionLocationTypeOutdoor; | |
NSError *error = nil; | |
_session = [[HKWorkoutSession alloc] initWithHealthStore:_healthStore configuration:_workoutConfig error:&error]; | |
if(_session == nil) { | |
NSLog(@"didFailWithError: %@", error); | |
return; | |
} | |
_session.delegate = self; | |
// builder setup | |
_builder = [_session associatedWorkoutBuilder]; | |
_builder.delegate = self; | |
HKLiveWorkoutDataSource *source = [[HKLiveWorkoutDataSource alloc] initWithHealthStore:_healthStore workoutConfiguration:_workoutConfig]; | |
// only heart rate | |
NSSet<HKQuantityType *> *typesToCollect = source.typesToCollect; | |
for (HKQuantityType *type in typesToCollect) { | |
[source disableCollectionForType:type]; | |
} | |
HKQuantityType *heartrate = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; | |
[source enableCollectionForType:heartrate predicate:nil]; | |
_builder.dataSource = source; | |
[_builder beginCollectionWithStartDate:[NSDate date] completion:^(BOOL success, NSError * _Nullable error) { | |
NSLog(@"beginCollectionWithStartDate: %@, %@", success ? @"OK" : @"ERROR", error); | |
}]; | |
} | |
- (void)workoutBuilder:(HKLiveWorkoutBuilder *)workoutBuilder didCollectDataOfTypes:(NSSet<HKSampleType *> *)collectedTypes { | |
HKQuantityType *heartRateSampleType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; | |
HKStatistics *stat = [workoutBuilder statisticsForType:heartRateSampleType]; | |
double value = [stat.mostRecentQuantity doubleValueForUnit:[HKUnit unitFromString:@"count/min"]]; | |
int heartrate = (int)round(value); | |
dispatch_async(dispatch_get_main_queue(), ^{ | |
[self.heartrateLabel setText:[NSString stringWithFormat:@"HR %d count/min", heartrate]]; | |
NSLog(@"HR %d count/min", heartrate); | |
}); | |
} | |
- (void)willActivate { | |
// This method is called when watch view controller is about to be visible to user | |
[super willActivate]; | |
} | |
- (void)didDeactivate { | |
// This method is called when watch view controller is no longer visible | |
[super didDeactivate]; | |
} | |
- (IBAction)didSelectedStart { | |
[self.startButton setHidden:YES]; | |
[self.stopButton setHidden:NO]; | |
[[WKInterfaceDevice currentDevice] playHaptic:WKHapticTypeStart]; | |
[_session startActivityWithDate:[NSDate date]]; | |
} | |
- (IBAction)didSelectedStop { | |
[self.stopButton setHidden:YES]; | |
[_builder discardWorkout]; | |
_builder = nil; | |
[_session end]; | |
} | |
- (void)workoutSession:(HKWorkoutSession *)workoutSession | |
didChangeToState:(HKWorkoutSessionState)toState | |
fromState:(HKWorkoutSessionState)fromState | |
date:(NSDate *)date { | |
if(toState == HKWorkoutSessionStatePrepared) { | |
self.stateLabel.text = @"state: Prepared"; | |
} else if(toState == HKWorkoutSessionStateNotStarted) { | |
self.stateLabel.text = @"state: NotStarted"; | |
} else if(toState == HKWorkoutSessionStateRunning) { | |
self.stateLabel.text = @"state: Running"; | |
} else if(toState == HKWorkoutSessionStatePaused) { | |
self.stateLabel.text = @"state: Stopped"; | |
} else if(toState == HKWorkoutSessionStateEnded) { | |
self.stateLabel.text = @"state: Ended"; | |
} | |
} | |
- (void)workoutSession:(HKWorkoutSession *)workoutSession didFailWithError:(NSError *)error { | |
NSLog(@"didFailWithError %@", error); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment