Skip to content

Instantly share code, notes, and snippets.

@Ushio
Created December 18, 2018 01:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ushio/cf5be41a2b0f52112240ff05c6f84fc0 to your computer and use it in GitHub Desktop.
Save Ushio/cf5be41a2b0f52112240ff05c6f84fc0 to your computer and use it in GitHub Desktop.
HKLiveWorkoutBuilder
#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