Skip to content

Instantly share code, notes, and snippets.

@ankitthakur
Last active August 29, 2015 14:16
Show Gist options
  • Save ankitthakur/6b245f4d836b5ca8ba46 to your computer and use it in GitHub Desktop.
Save ankitthakur/6b245f4d836b5ca8ba46 to your computer and use it in GitHub Desktop.
Apple HealthKitUtilities
//
// AppleHealthKitUtilities.swift
// AppleHealthKitPOC
//
// Created by Ankit Thakur on 09/01/15.
// Copyright (c) 2015 Ankit Thakur. All rights reserved
//
import UIKit
import HealthKit
enum HeightQuanityType{
case NotSet
case Millimeters
case Centimeters
case Meters
case Inches
case Feet
}
enum WeightQuanityType{
case NotSet
case Pounds
case Grams
case Kilograms
case Ounce
}
enum BloodType : Int {
case NotSet
case APositive
case ANegative
case BPositive
case BNegative
case ABPositive
case ABNegative
case OPositive
case ONegative
}
let calendarUnit:NSCalendarUnit = .DayCalendarUnit | .YearCalendarUnit | .MonthCalendarUnit | .HourCalendarUnit | .MinuteCalendarUnit | .SecondCalendarUnit | .WeekOfMonthCalendarUnit | .WeekdayCalendarUnit;
protocol Instantiable {
init()
}
let inchesToMeter : Double = 0.0254
class AppleHealthKitUtilities: NSObject {
var healthKitStore = HKHealthStore();
var isPermissionGranted:Bool = false;
// singleton
class var sharedInstance: AppleHealthKitUtilities {
struct Static {
static var instance: AppleHealthKitUtilities?
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = AppleHealthKitUtilities()
Static.instance!.initializForPermissions();
}
return Static.instance!
}
func initializForPermissions(){
healthKitStore.requestAuthorizationToShareTypes(self.requestForSharePermissions() as! Set<NSObject>, readTypes: self.requestForReadPermissions() as! Set<NSObject>) { (success:Bool, error:NSError!) -> Void in
self.isPermissionGranted = success;
NSNotificationCenter.defaultCenter().postNotificationName("permissiongranted", object: nil);
// [[NSNotificationCenter defaultCenter] postNotificationName:@"stopAndPauseMedia" object:nil];
if (!success) {
NSLog("You didn't allow HealthKit to access these read/write data types. In your app, try to handle this error gracefully when a user decides not to provide access. The error was: %@. If you're using a simulator, try it on a device.", error);
}
else{
}
}
}
// request permissions
func requestForPermissions(completion: ((Bool, NSError!) -> Void)!){
healthKitStore.requestAuthorizationToShareTypes(self.requestForSharePermissions() as! Set<NSObject>, readTypes: self.requestForReadPermissions() as! Set<NSObject>) { (success:Bool, error:NSError!) -> Void in
if (!success) {
NSLog("You didn't allow HealthKit to access these read/write data types. In your app, try to handle this error gracefully when a user decides not to provide access. The error was: %@. If you're using a simulator, try it on a device.", error);
}
else{
}
completion(success, error);
}
}
func requestForReadPermissions() -> NSSet {
let bmiQuantityType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMassIndex);
let heightQuantityType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight);
let stepCountQuantityType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount);
let weightQuantityType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass);
let birthdayType:HKCharacteristicType = HKObjectType.characteristicTypeForIdentifier(HKCharacteristicTypeIdentifierDateOfBirth);
let biologicalSexType:HKCharacteristicType = HKObjectType.characteristicTypeForIdentifier(HKCharacteristicTypeIdentifierBiologicalSex);
let workoutType = HKQuantityType.workoutType();
let walkingRunning = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning);
return NSSet(array: [bmiQuantityType, heightQuantityType, stepCountQuantityType, weightQuantityType, birthdayType, biologicalSexType, workoutType, walkingRunning]);
}
func requestForSharePermissions() -> NSSet {
let bmiQuantityType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMassIndex);
let heightQuantityType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight);
let stepCountQuantityType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount);
let weightQuantityType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass);
let workoutType = HKQuantityType.workoutType();
let walkingRunning = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning);
return NSSet(array: [bmiQuantityType, heightQuantityType, stepCountQuantityType, weightQuantityType, workoutType, walkingRunning]);
}
// converters
func convertHeight(heightQuanityType:HeightQuanityType, toHeightQuanityType:HeightQuanityType, value:Double) -> Double{
let currentUnit:HKUnit = self.heightUnit(heightQuanityType);
let toUnit:HKUnit = self.heightUnit(toHeightQuanityType);
let height = HKQuantity(unit: currentUnit, doubleValue: value);
let newHeight = height.doubleValueForUnit(toUnit);
return newHeight;
}
func convertHeight(height:HKQuantity!, toHeightQuanityType:HeightQuanityType!) -> Double{
let toUnit:HKUnit = self.heightUnit(toHeightQuanityType);
let newHeight = height.doubleValueForUnit(toUnit);
return newHeight;
}
func convertWeight(weightQuanityType:WeightQuanityType!, toWeightQuanityType:WeightQuanityType!, value:Double!) -> Double{
if weightQuanityType == .NotSet {
}
let currentUnit:HKUnit = self.weightUnit(weightQuanityType);
let toUnit:HKUnit = self.weightUnit(toWeightQuanityType);
let weight = HKQuantity(unit: currentUnit, doubleValue: value);
let newWeight = weight.doubleValueForUnit(toUnit);
return newWeight;
}
func convertWeight(weight:HKQuantity!, toWeightQuanityType:WeightQuanityType!) -> Double{
let toUnit:HKUnit = self.weightUnit(toWeightQuanityType);
let newWeight = weight.doubleValueForUnit(toUnit);
return newWeight;
}
// units
func heightUnit(heightQuanityType:HeightQuanityType) -> HKUnit{
switch heightQuanityType {
case .Millimeters:
return HKUnit.meterUnitWithMetricPrefix(.Milli)
case .Centimeters:
return HKUnit.meterUnitWithMetricPrefix(.Centi)
case .Inches:
return HKUnit.inchUnit()
case .Feet:
return HKUnit.footUnit()
default: //meters
return HKUnit.meterUnit()
}
}
func weightUnit(weightQuanityType:WeightQuanityType) -> HKUnit{
switch weightQuanityType {
case .Pounds:
return HKUnit.poundUnit()
case .Kilograms:
return HKUnit(fromString:"kg")
case .Ounce:
return HKUnit.ounceUnit()
default: // Grams
return HKUnit.gramUnit()
}
}
// read data
func readDateOfBirthInformation() -> NSDate!{
var dateOfBirth = NSDate();
var dateOfBirthError: NSError?
let birthDate = self.healthKitStore.dateOfBirthWithError(&dateOfBirthError)
as NSDate?
if let error = dateOfBirthError{
println("Could not read user's date of birth")
} else {
if let dob = birthDate{
dateOfBirth = dob;
println("The user DOB is \(dateOfBirth)")
} else {
println("User has not specified her date of birth yet")
}
}
return dateOfBirth;
}
func readAgeInformation() -> Int{
var birthAge = 0;
var dateOfBirthError: NSError?
let birthDate = self.healthKitStore.dateOfBirthWithError(&dateOfBirthError)
as NSDate?
if let error = dateOfBirthError{
println("Could not read user's date of birth")
} else {
if let dateOfBirth = birthDate{
let formatter = NSNumberFormatter()
let now = NSDate()
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate:dateOfBirth, toDate:NSDate(), options:NSCalendarOptions.MatchStrictly)
birthAge = components.year
println("The user is \(birthAge) years old")
} else {
println("User has not specified her date of birth yet")
}
}
return birthAge;
}
func readBiologicalSexInformation() -> GenderType{
var genderType:GenderType = .NotSet;
var biologicalSexError: NSError?
var biologicalSexObject:HKBiologicalSexObject? = self.healthKitStore.biologicalSexWithError(&biologicalSexError);
if let error = biologicalSexError{
println("Could not read user's date of birth")
} else {
println("The user gender is \(biologicalSexObject?.biologicalSex)")
switch biologicalSexObject!.biologicalSex {
case .Female:
genderType = .Female;
break
case .Male:
genderType = .Male;
break
default:
genderType = .NotSet;
break
}
}
return genderType;
}
func readBloodGroupTypeInformation() -> BloodType{
var bloodType:BloodType = .NotSet;
var bloodTypeError: NSError?
var bloodTypeObject:HKBloodTypeObject? = self.healthKitStore.bloodTypeWithError(&bloodTypeError);
if let error = bloodTypeError{
println("Could not read user's date of birth")
} else {
switch bloodTypeObject!.bloodType {
case .NotSet:
bloodType = .NotSet;
break
case .APositive:
bloodType = .APositive;
break
case .ANegative:
bloodType = .ANegative;
break
case .BPositive:
bloodType = .BPositive;
break
case .BNegative:
bloodType = .BNegative;
break
case .ABPositive:
bloodType = .ABPositive;
break
case .ABNegative:
bloodType = .ABNegative;
break
case .OPositive:
bloodType = .OPositive;
break
case .ONegative:
bloodType = .ONegative;
break
}
}
return bloodType;
}
func readUserHeightInUnits(unit:HeightQuanityType, completion: ((Double!, NSError?) -> Void)!) ->Void{
let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight)
self.readMostRecentSample(sampleType, completion: {(quantitySample:HKSample!, error:NSError!) -> Void in
var userHeight:Double = 0;
var height:HKQuantitySample?;
if(error != nil)
{
println("Error reading weight from HealthKit Store: \(error.localizedDescription)")
}
else{
height = quantitySample as? HKQuantitySample;
if let quantity = height?.quantity {
userHeight = self.convertHeight(quantity, toHeightQuanityType: unit);
println("The user height is \(userHeight)")
}
}
completion(userHeight, error);
});
}
func readUserWeightInUnits(unit:WeightQuanityType, completion: ((Double!, NSError?) -> Void)!) ->Void{
let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass)
self.readMostRecentSample(sampleType, completion: {(quantitySample:HKSample!, error:NSError!) -> Void in
var userWeight:Double = 0;
var weight:HKQuantitySample?;
if(error != nil)
{
println("Error reading weight from HealthKit Store: \(error.localizedDescription)")
}
else{
weight = quantitySample as? HKQuantitySample;
if let quantity = weight?.quantity {
userWeight = self.convertWeight(quantity, toWeightQuanityType: unit);
println("The user weight is \(userWeight)")
}
}
completion(userWeight, error);
});
}
func readMostRecentSample(sampleType:HKSampleType , completion: ((HKSample!, NSError!) -> Void)!)
{
// 1. Build the Predicate
let past = NSDate.distantPast() as! NSDate
let now = NSDate()
let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(past, endDate:now, options: .None)
// Build the sort descriptor to return the samples in descending order
let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierEndDate, ascending: false)
// we want to limit the number of samples returned by the query to just 1 (the most recent)
let limit = 1
// Build samples query
let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: nil, limit: limit, sortDescriptors: [sortDescriptor])
{ (sampleQuery, results, error ) -> Void in
if let queryError = error {
completion(nil,error)
return;
}
// Get the first sample
let mostRecentSample = results.first as? HKQuantitySample
// Execute the completion closure
if completion != nil {
completion(mostRecentSample,nil)
}
}
// Execute the Query
self.healthKitStore.executeQuery(sampleQuery)
}
override class func automaticallyNotifiesObserversForKey(key: String) -> Bool{
return true;
}
func saveHeightSample(heightInInch:Double, withCompletion completion: ((Bool, NSError!) -> Void)!){
// inches to meter conversion
let heightInMeter : Double = heightInInch * inchesToMeter
let meterUnit:HKUnit = HKUnit.meterUnit();
let heightQuantity = HKQuantity(unit: meterUnit, doubleValue: Double(heightInMeter))
let heightType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight)
let now = NSDate()
let heightSample = HKQuantitySample(type: heightType, quantity: heightQuantity, startDate: now, endDate: now)
self.healthKitStore.saveObject(heightSample, withCompletion: { (success : Bool, error : NSError!) -> Void in
if(!success)
{
NSLog("An error occured saving the height sample %@. In your app, try to handle this gracefully. The error was: %@.", heightSample, error)
} else {
println("Height sample saved successfully!!!")
}
completion(success, error);
})
}
func saveWeightSample(weightInGrams:Double, withCompletion completion: ((Bool, NSError!) -> Void)!){
// inches to meter conversion
var gramUnit:HKUnit = HKUnit.gramUnit();
let weightQuantity = HKQuantity(unit: gramUnit, doubleValue: Double(weightInGrams))
let weightType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass)
let now = NSDate()
let weightSample = HKQuantitySample(type: weightType, quantity: weightQuantity, startDate: now, endDate: now)
self.healthKitStore.saveObject(weightSample, withCompletion: { (success : Bool, error : NSError!) -> Void in
if(!success)
{
NSLog("An error occured saving the weight sample %@. In your app, try to handle this gracefully. The error was: %@.", weightSample, error)
} else {
println("Weight sample saved successfully!!!")
}
completion(success, error);
})
}
func saveBMISample(bmi:Double, withCompletion completion: ((Bool, NSError!) -> Void)!){
// 1. Create a BMI Sample
let bmiType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMassIndex)
let bmiQuantity = HKQuantity(unit: HKUnit.countUnit(), doubleValue: bmi)
let now = NSDate()
let bmiSample = HKQuantitySample(type: bmiType, quantity: bmiQuantity, startDate:now, endDate: now)
// 2. Save the sample in the store
healthKitStore.saveObject(bmiSample, withCompletion: { (success, error) -> Void in
if( error != nil ) {
println("Error saving BMI sample: \(error.localizedDescription)")
} else {
println("BMI sample saved successfully!!!")
}
completion(success, error);
})
}
func readRunningWorkOuts(completion: (([AnyObject]!, NSError!) -> Void)!){
// 1. Predicate to read only running workouts
let predicate = HKQuery.predicateForWorkoutsWithWorkoutActivityType(HKWorkoutActivityType.Running)
// 2. Order the workouts by date
let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)
// 3. Create the query
let sampleQuery = HKSampleQuery(sampleType: HKWorkoutType.workoutType(), predicate: predicate, limit: 0, sortDescriptors: [sortDescriptor])
{ (sampleQuery, results, error ) -> Void in
var workouts:Array<HKWorkoutModel> = [];
if let queryError = error {
println( "There was an error while reading the samples: \(queryError.localizedDescription)")
}
else{
// println("============================");
// println("reading workouts: \(results)");
// println("============================");
for object in results{
let wObject:HKWorkout = object as! HKWorkout;
var workout:HKWorkoutModel = HKWorkoutModel(workout: wObject);
workouts.append(workout);
}
}
completion(workouts, error)
}
// 4. Execute the query
healthKitStore.executeQuery(sampleQuery)
}
func groupByDays(routeModels: Array<HKWorkoutModel>) -> [WorkoutEntry] {
var result:[WorkoutEntry] = [] // array of <monthIndex, array of routemodels>
let formatter = NSNumberFormatter()
let now = NSDate();
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now)
let currentWeek = components.weekday;
let currentDay = components.day;
let currentMonth = components.month;
var dayArray:[Int] = [];
for (var index:Int = 0; index < currentDay; index++){
dayArray.append(index+1);
}
var dayRecords:Array<HKWorkoutModel> = [];
// get array on days
for routeModel in routeModels {
let formatter = NSNumberFormatter()
let now = (routeModel as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now)
let day:Int = components.day;
let month:Int = components.month;
if(month == currentMonth){
if !contains(dayArray, day){
dayArray.append(day);
}
}
}
// looping on days
for m in dayArray {
let dayIndex = m;
var workoutRouteModels :Array<HKWorkoutModel> = [];
//grouping array of records by current day (m).
for record in routeModels {
let formatter = NSNumberFormatter()
let now = (record as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
let day = components.day;
if day == dayIndex {
workoutRouteModels.append(record);
}
}
var entry:WorkoutEntry = (dayIndex, workoutRouteModels);
result.append(entry);
}
result.sort { (workoutEntry1: WorkoutEntry, workoutEntry2: WorkoutEntry) -> Bool in
return (workoutEntry1.index < workoutEntry2.index)
};
return result
}
func groupActivitiesByDays(routeModels: Array<HKWorkoutModel>) -> [WorkoutEntry] {
var result:[WorkoutEntry] = [] // array of <monthIndex, array of routemodels>
let formatter = NSNumberFormatter()
let now = NSDate();
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now)
let currentWeek = components.weekday;
let currentDay = components.day;
let currentMonth = components.month;
let initialDay = currentDay-7;
var dayArray:[Int] = [1,2,3,4,5,6,7];
var dayRecords:Array<HKWorkoutModel> = [];
// looping on days
for m in dayArray {
let dayIndex = m;
var workoutRouteModels :Array<HKWorkoutModel> = [];
var routemodels:Array<HKWorkoutModel> = routeModels;
routemodels.sort { (routeModel1: HKWorkoutModel, routeModel2: HKWorkoutModel) -> Bool in
return (routeModel1.workoutStartTime!.timeIntervalSince1970 < routeModel2.workoutStartTime!.timeIntervalSince1970)
};
//grouping array of records by current day (m).
for record in routemodels {
let formatter = NSNumberFormatter()
let now = (record as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
var day = components.day;
day = currentDay - day;
if day == dayIndex {
workoutRouteModels.append(record);
}
}
var entry:WorkoutEntry = (dayIndex, workoutRouteModels);
result.append(entry);
}
return result
}
func groupWeekDataByDays(routeModels: Array<HKWorkoutModel>) -> [WorkoutEntry] {
var result:[WorkoutEntry] = [] // array of <monthIndex, array of routemodels>
let formatter = NSNumberFormatter()
let now = NSDate();
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now)
let currentWeek = components.weekday;
var dayArray:[Int] = [1,2,3,4,5,6,7];
var dayRecords:Array<HKWorkoutModel> = [];
// looping on days
for m in dayArray {
let dayIndex = m;
var workoutRouteModels :Array<HKWorkoutModel> = [];
var routemodels:Array<HKWorkoutModel> = routeModels;
routemodels.sort { (routeModel1: HKWorkoutModel, routeModel2: HKWorkoutModel) -> Bool in
return (routeModel1.workoutStartTime!.timeIntervalSince1970 < routeModel2.workoutStartTime!.timeIntervalSince1970)
};
//grouping array of records by current day (m).
for record in routemodels {
let formatter = NSNumberFormatter()
let now = (record as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
let day = components.weekday;
if day == dayIndex {
workoutRouteModels.append(record);
}
}
var entry:WorkoutEntry = (dayIndex, workoutRouteModels);
result.append(entry);
}
return result
}
func groupMonthDataByWeeks(routeModels: Array<HKWorkoutModel>) -> [WorkoutEntry] {
var result:[WorkoutEntry] = [] // array of <monthIndex, array of routemodels>
let formatter = NSNumberFormatter()
let now = NSDate();
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now)
let currentMonth = components.month;
var weekArray:[Int] = [1,2,3,4,5,6,7];
var weekRecords:Array<HKWorkoutModel> = [];
// looping on days
for m in weekArray {
let monthIndex = m;
var workoutRouteModels :Array<HKWorkoutModel> = [];
var routemodels:Array<HKWorkoutModel> = routeModels;
routemodels.sort { (routeModel1: HKWorkoutModel, routeModel2: HKWorkoutModel) -> Bool in
return (routeModel1.workoutStartTime!.timeIntervalSince1970 < routeModel2.workoutStartTime!.timeIntervalSince1970)
};
//grouping array of records by current week (m).
for record in routemodels {
let formatter = NSNumberFormatter()
let now = (record as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
let month = components.month;
if month == monthIndex {
workoutRouteModels.append(record);
}
}
var entry:WorkoutEntry = (monthIndex, workoutRouteModels);
result.append(entry);
}
return result
}
func groupByWeek(routeModels: Array<HKWorkoutModel>) -> [WorkoutEntry] {
var result:Array<WorkoutEntry> = [] // array of <monthIndex, array of routemodels>
let formatter = NSNumberFormatter()
let now = NSDate();
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
let currentWeek = components.weekOfMonth;
let currentMonth = components.month;
var weekArray:[Int] = [];
var weekRecords:Array<HKWorkoutModel> = [];
for routeModel in routeModels {
let formatter = NSNumberFormatter()
let now = (routeModel as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now)
println(components);
let week = components.weekOfMonth;
let month = components.month;
if(month == currentMonth){
if !contains(weekArray, week){
weekArray.append(week);
}
}
}
// looping on weeks
for m in weekArray {
let weekIndex = m;
var workoutRouteModels :Array<HKWorkoutModel> = [];
//grouping array of records by current week (m).
// var routemodels:Array<HKWorkoutModel> = routeModels;
//
// routemodels.sort { (routeModel1: HKWorkoutModel, routeModel2: HKWorkoutModel) -> Bool in
// return (routeModel1.workoutStartTime!.timeIntervalSince1970 < routeModel2.workoutStartTime!.timeIntervalSince1970)
// };
for record in routeModels {
let formatter = NSNumberFormatter()
let now = (record as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
let week = components.weekOfMonth;
if week == weekIndex {
workoutRouteModels.append(record);
}
}
var entry:WorkoutEntry = (weekIndex, workoutRouteModels);
result.append(entry);
}
return result
}
func groupByMonthAndYear(routeModels: [HKWorkoutModel]) -> [WorkoutEntry] {
var result:[WorkoutEntry] = [] // array of <monthIndex, array of routemodels>
let formatter = NSNumberFormatter()
let now = NSDate();
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
let currentMonth = components.month;
let currentYear = components.year;
var monthArray:[Int] = [];
var monthRecords:Array<HKWorkoutModel> = [];
var routemodels:Array<HKWorkoutModel> = routeModels;
routemodels.sort { (routeModel1: HKWorkoutModel, routeModel2: HKWorkoutModel) -> Bool in
return (routeModel1.workoutStartTime!.timeIntervalSince1970 < routeModel2.workoutStartTime!.timeIntervalSince1970)
};
// get array on months
for routeModel in routemodels {
let formatter = NSNumberFormatter()
let now = (routeModel as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
let month = components.month;
let year = components.year;
if(year == currentYear){
if !contains(monthArray, month){
monthArray.append(month);
}
}
}
// looping on months
for m in monthArray {
let monthIndex = m;
var workoutRouteModels :[HKWorkoutModel] = [];
//grouping array of records by current month (m).
for record in routeModels {
let formatter = NSNumberFormatter()
let now = (record as HKWorkoutModel).workoutStartTime!;
let components = NSCalendar.currentCalendar().components(calendarUnit, fromDate: now);
let month = components.month;
if month == monthIndex {
workoutRouteModels.append(record);
}
}
var entry:WorkoutEntry = (monthIndex, workoutRouteModels);
result.append(entry);
}
return result
}
}
@faganello60
Copy link

Hello, DO you know ho do in OBJ C?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment