9 #import <CoreData/CoreData.h> 10 #import <HealthKit/HealthKit.h> 26 id<Z5HealthConnectionProtocol> healthConnectDelegate;
104 + (UIColor *) colorForAuthority: (NSNumber *) authorityValue
108 switch ([authorityValue integerValue]) {
109 case HKAuthorizationStatusSharingAuthorized:
112 case HKAuthorizationStatusNotDetermined:
115 case HKAuthorizationStatusSharingDenied:
118 case HKErrorAuthorizationDenied:
121 case HKErrorAuthorizationNotDetermined:
127 + (NSString *) captionForAuthority: (NSNumber *) authorityValue
131 switch ([authorityValue integerValue]) {
132 case HKAuthorizationStatusSharingAuthorized:
134 ret =
@"sharing authorized";
136 case HKAuthorizationStatusNotDetermined:
138 ret =
@"status not determined";
140 case HKAuthorizationStatusSharingDenied:
142 ret =
@"Sharing denied";
144 case HKErrorAuthorizationDenied:
146 ret =
@"authorization denied";
148 case HKErrorAuthorizationNotDetermined:
150 ret =
@"authorization not determined";
161 [healthKitOpQueue setMaxConcurrentOperationCount:36];
190 - (void) logGallery: (NSNumber *)galleryChoice caption: (NSString *) caption
192 NSLog(
@"Z5LocalDataController.logGallery: %@ caption: %@", galleryChoice, caption);
194 switch ([galleryChoice integerValue]) {
198 for (
MenuItem *mItem in localDataMenuItems) {
199 NSLog(
@"Z5LocalDataController.logGallery: mItem-name: %@", mItem.name);
206 for (
Meal *mItem in localDataMeals) {
207 NSLog(
@"Z5LocalDataController.logGallery: meal: %@", mItem);
212 NSLog(
@"Z5LocalDataController.logGallery: %@", galleryChoice);
221 NSError *error = nil;
227 NSLog(
@"Z5LocalDataController.saveContext: Unresolved error %@, %@", error, [error userInfo]);
232 NSLog(
@"Z5LocalDataController.saveContext: write user prefs");
240 #pragma mark - Core Data stack 248 if (_managedObjectContext != nil) {
249 return _managedObjectContext;
252 NSPersistentStoreCoordinator *coordinator = [
self persistentStoreCoordinator];
253 if (coordinator != nil) {
255 _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
256 [_managedObjectContext setPersistentStoreCoordinator:coordinator];
258 return _managedObjectContext;
267 if (_managedObjectModel != nil) {
268 return _managedObjectModel;
271 NSBundle *mainb = [NSBundle mainBundle];
275 NSURL *modelURL = [mainb URLForResource:@"nutritionMenuModel" withExtension:@"momd"];
276 _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
277 return _managedObjectModel;
286 if (_persistentStoreCoordinator != nil) {
287 return _persistentStoreCoordinator;
290 NSURL *storeURL = [[
self applicationDocumentsDirectory] URLByAppendingPathComponent:@"ProjectName.sqlite"];
292 NSError *error = nil;
293 _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[
self managedObjectModel]];
294 NSDictionary *options = @{
295 NSMigratePersistentStoresAutomaticallyOption : @YES,
296 NSInferMappingModelAutomaticallyOption: @YES
298 if (![_persistentStoreCoordinator
299 addPersistentStoreWithType:NSSQLiteStoreType
301 URL:storeURL options:options
325 NSLog(
@"Z5LocalDataController.persistentStoreCoordinator: Unresolved error %@, %@", error, [error userInfo]);
330 return _persistentStoreCoordinator;
334 #pragma mark - Meal Data 335 - (NSArray<
Meal *> *) findMealsWithDate: (NSDate *)findDate
341 - (NSArray<
Meal *> *) findMealsThisMonthDate: (NSDate *)findDate
347 - (NSArray<
Meal *> *) retrieveAllMeals: (NSNumber *)galleryNo
349 NSLog(
@"Z5LocalDataController.retrieveAllMeals: gallery: %@", galleryNo);
353 NSLog(
@"Z5LocalDataController.retrieveAllMeals: meals retrieved: %lu", (
unsigned long)[ret count]);
358 - (void) eraseMealsThisMonthDate: (NSDate *)findDate
363 - (NSArray<
Meal *> *) findOrCreateMealWithDate: (NSDate *)findDate
366 NSLog(
@"Z5LocalDataController.findOrCreateMealWithDate: returning %lu meal(s)", (
unsigned long)[ret count]);
369 - (Boolean) removeMealWithRandomkey: (NSString *)removeKey
375 - (void) todaysMealRequested: (NSDate *)date
378 _todaysMeal = [dailyMeal lastObject];
380 _todaysMeal.containedItem = [NSSet setWithArray:todaysMenuItems];
381 _todaysMeal.orderDate = date;
384 [_todaysMenuItems removeAllObjects];
385 _todaysMenuItems = nil;
388 - (void) todaysMealConsumed: (NSDate *)date forDelegate: (
id<Z5HealthConnectionProtocol>)jingo
403 _todaysMeal.consumeDate = date;
404 NSLog(
@"Z5LocalDataController.todaysMealConsumed: rating: %3.2f", [_todaysMeal.rating floatValue]);
407 - (void) todaysMealRated: (
float)rating
409 NSNumber *ratingNumber = [NSNumber numberWithFloat:rating];
410 [_todaysMeal setRating:ratingNumber];
415 NSLog(
@"Z5LocalDataController.todaysMealSkipped: _todaysMeal: %@", _todaysMeal);
422 NSString *removeKey = [_todaysMeal randomkey];
425 - (NSDate *) toLocalTime: (NSDate *)grenwich
427 NSCalendar *gregorian = [[NSCalendar alloc]
428 initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
429 NSDateComponents *dayComponents =
430 [gregorian components:(NSCalendarUnitDay |
431 NSCalendarUnitMonth |
432 NSCalendarUnitYear) fromDate:grenwich];
433 NSInteger day = [dayComponents day];
434 NSInteger month = [dayComponents month];
435 NSInteger year = [dayComponents year];
437 NSCalendar *calendar = [NSCalendar currentCalendar];
438 [calendar setTimeZone: [NSTimeZone systemTimeZone]];
441 NSDateComponents *timeZoneComps=[[NSDateComponents alloc] init];
442 [timeZoneComps setSecond:0];
443 [timeZoneComps setMinute:0];
444 [timeZoneComps setHour:0];
445 [timeZoneComps setDay:day];
446 [timeZoneComps setMonth:month];
447 [timeZoneComps setYear:year];
448 [timeZoneComps setSecond:0];
450 NSDate *ret = [calendar dateFromComponents:timeZoneComps];
455 #pragma mark - MenuItem Data 456 - (
MenuItem *) findMenuItemWithRandomkey: (NSString *)randomkey
465 - (
MenuItem *) findOrCreateMenuItemWithRandomkey: (NSString *)randomkey
469 NSLog(
@"Z5LocalDataController.findOrCreateMenuItemWithRandomkey: randomkey: %@ name: %@", randomkey, [ret name]);
476 - (
MenuItem *) findMenuItemWithFileIdentification: (NSString *)googlefileid
483 - (
MenuItem *) findOrCreateMenuItemWithFileIdentification: (NSString *)googlefileid
494 - (NSArray<
MenuItem *> *) retrieveAllMenuItems: (NSNumber *)galleryNo
501 - (void) removeMenuItemWithKey:(NSString *)moleculekey fromTree:(NSDictionary *)tree
516 - (
MenuItem *) findNextMenuItemForGallery: (NSNumber *) galleryNo afterPosition: (NSNumber *) positionInGallery
534 - (void) initGalleryPositionsRange: (NSRange) fetchAllRange
540 - (void) logTodaysMenu: (NSString *) caption
542 NSLog(
@"Z5LocalDataController.logTodaysMenu");
543 NSLog(
@"%@(logTodaysMenu) count: %ld", caption, (
unsigned long)[[
self todaysMenuItems] count]);
546 NSLog(
@"(logTodaysMenu) item: %@", mItem.name);
551 if (0 < [todaysParameters count]) {
555 NSLog(
@"Z5LocalDataController.logTodaysMenu: end");
558 #pragma mark - JSON formatter 560 - (NSString *)unitsForParameter:(NSString *)paramKeyStr
563 if ([paramKeyStr isEqualToString:
@"sodium"]) {
565 }
else if ([paramKeyStr isEqualToString:
@"total-fat"]) {
570 NSLog(
@"Z5LocalDataController.unitsForParameter: WHAT IS HERE? key: %@ ret: %@", paramKeyStr, ret);
574 - (NSMutableDictionary *) mergeJsonForUsdaNumbers:(NSDictionary *)usdaDictionary inMenuItem:(
MenuItem *)menuItem inContext:(UIView *) screen
579 NSEnumerator *enumerator = [usdaDictionary keyEnumerator];
581 while ((key = [enumerator nextObject])) {
583 NSString *keyStr = (NSString *)key;
584 NSLog(
@"Z5LocalDataController.mergeJsonForUsdaNumbers: keyStr: %@", keyStr);
585 id value = [usdaDictionary objectForKey:key];
586 if (![(NSString *)value isEqualToString:
@""]) {
587 NSString *valueStr = [NSString stringWithFormat:@"%@%@",(NSString *)value, [
self unitsForParameter:keyStr]];
588 [ret setObject:valueStr forKey:keyStr];
590 NSLog(
@"Z5LocalDataController.mergeJsonForUsdaNumbers: ret: %@", ret);
601 - (NSDictionary *) jsonForUsdaNumbersInMenuItem:(
MenuItem *)menuItem
609 if (![usdaNumbers isEqualToString:
@""]) {
610 NSData *existingUsdaNumbersData = [usdaNumbers dataUsingEncoding:NSUTF8StringEncoding];
611 NSError *err_init_json;
612 NSObject *extantUsdaJsonObj = [NSJSONSerialization JSONObjectWithData:existingUsdaNumbersData options:NSJSONReadingAllowFragments error:&err_init_json];
613 if (!err_init_json) {
614 if (extantUsdaJsonObj) {
615 if ([extantUsdaJsonObj isKindOfClass:[NSDictionary
class]]) {
620 return (NSDictionary *)extantUsdaJsonObj;
622 NSLog(
@"Z5LocalDataController.jsonForUsdaNumbersInMenuItem: class: %@", NSStringFromClass([extantUsdaJsonObj
class]));
627 NSLog(
@"Z5LocalDataController.vjsonForUsdaNumbersInMenuItem: err_init_json: %@", err_init_json);
628 NSLog(
@"Z5LocalDataController.jsonForUsdaNumbersInMenuItem: usdaNumbers: %@", usdaNumbers);
631 NSLog(
@"Z5LocalDataController.jsonForUsdaNumbersInMenuItem: no usdaNumbers");
634 NSLog(
@"Z5LocalDataController.jsonForUsdaNumbersInMenuItem: nil usdaNumbers");
638 #pragma mark - Health Kit 642 - (void) setUseHealthKit:(Boolean)useHealthKit
645 _usingHealthKit = [[NSNumber alloc] initWithBool:YES];
647 _usingHealthKit = [[NSNumber alloc] initWithBool:NO];
649 NSLog(
@"LocalData.setUsingHealthKit: %@", _usingHealthKit);
650 if ([_usingHealthKit boolValue]) {
666 NSLog(
@"LocalData.setupHealthKit: healthStore all ready set");
667 }
else if ([HKHealthStore isHealthDataAvailable]) {
668 self.healthStore = [[HKHealthStore alloc] init];
676 - (void) getAddedAuthorizationToShare: (NSSet *)writeNutrTypes
677 forDelegate: (
id<Z5HealthConnectionProtocol>) requestFrom
679 healthConnectDelegate = requestFrom;
680 [
self.healthStore requestAuthorizationToShareTypes:writeNutrTypes
681 readTypes:writeNutrTypes
682 completion:^(BOOL success, NSError *error) {
684 NSLog(@"Z5LocalDataController.getAddedAuthorizationToWrite: 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: %@", error);
688 NSLog(@"Z5LocalDataController.getAddedAuthorizationToShare: authorization success");
690 dispatch_async(dispatch_get_main_queue(), ^{
695 [
self->healthConnectDelegate updateToAuthorizationOK];
699 NSLog(
@"Z5LocalDataController.getAddedAuthorizationToWrite: end");
708 _hkQuantityTypes = [[NSArray alloc] initWithObjects:
709 HKQuantityTypeIdentifierDietaryBiotin,
710 HKQuantityTypeIdentifierDietaryCaffeine,
711 HKQuantityTypeIdentifierDietaryCalcium,
712 HKQuantityTypeIdentifierDietaryCarbohydrates,
713 HKQuantityTypeIdentifierDietaryChloride,
714 HKQuantityTypeIdentifierDietaryCholesterol,
715 HKQuantityTypeIdentifierDietaryChromium,
716 HKQuantityTypeIdentifierDietaryCopper,
717 HKQuantityTypeIdentifierDietaryEnergyConsumed,
718 HKQuantityTypeIdentifierDietaryFatMonounsaturated,
719 HKQuantityTypeIdentifierDietaryFatPolyunsaturated,
720 HKQuantityTypeIdentifierDietaryFatSaturated,
721 HKQuantityTypeIdentifierDietaryFatTotal,
722 HKQuantityTypeIdentifierDietaryFiber,
723 HKQuantityTypeIdentifierDietaryFolate,
724 HKQuantityTypeIdentifierDietaryIodine,
725 HKQuantityTypeIdentifierDietaryIron,
726 HKQuantityTypeIdentifierDietaryMagnesium,
727 HKQuantityTypeIdentifierDietaryManganese,
728 HKQuantityTypeIdentifierDietaryMolybdenum,
729 HKQuantityTypeIdentifierDietaryNiacin,
730 HKQuantityTypeIdentifierDietaryPantothenicAcid,
731 HKQuantityTypeIdentifierDietaryPhosphorus,
732 HKQuantityTypeIdentifierDietaryPotassium,
733 HKQuantityTypeIdentifierDietaryProtein,
734 HKQuantityTypeIdentifierDietaryRiboflavin,
735 HKQuantityTypeIdentifierDietarySelenium,
736 HKQuantityTypeIdentifierDietarySodium,
737 HKQuantityTypeIdentifierDietarySugar,
738 HKQuantityTypeIdentifierDietaryThiamin,
739 HKQuantityTypeIdentifierDietaryVitaminA,
740 HKQuantityTypeIdentifierDietaryVitaminB12,
741 HKQuantityTypeIdentifierDietaryVitaminB6,
742 HKQuantityTypeIdentifierDietaryVitaminC,
743 HKQuantityTypeIdentifierDietaryVitaminD,
744 HKQuantityTypeIdentifierDietaryVitaminE,
745 HKQuantityTypeIdentifierDietaryVitaminK,
746 HKQuantityTypeIdentifierDietaryWater,
747 HKQuantityTypeIdentifierDietaryZinc,
752 NSString *thisone = [_hkQuantityTypes[j] description];
765 int notDetermined = 0;
767 int itemAuthorized = 0;
771 HKQuantityType *hkQtype = [HKObjectType quantityTypeForIdentifier:hkQtypeString];
774 HKAuthorizationStatus status = [
self.healthStore authorizationStatusForType:hkQtype];
775 NSNumber *statusNumb = [NSNumber numberWithInt:status];
776 NSDate *freshAuthorityDate;
778 NSMutableDictionary *knownAuthority = [healthKitNutritionAuthorityDict objectForKey:hkQtypeString];
780 if (knownAuthority) {
781 NSNumber *previousAuthority = [knownAuthority objectForKey:@"value"];
782 NSDate *knownAuthorityDate = [knownAuthority objectForKey:@"data"];
784 if ([statusNumb isEqualToNumber:previousAuthority]) {
786 freshAuthorityDate = knownAuthorityDate;
790 NSLog(
@"LocalData.validateHealthKitAuthority: old auth: %@ new auth: %@", previousAuthority, statusNumb);
791 freshAuthorityDate = [NSDate dateWithTimeIntervalSinceNow:0];
794 freshAuthorityDate = [NSDate dateWithTimeIntervalSinceNow:0];
796 NSDictionary *freshAuthorityDict = [[NSDictionary alloc] initWithObjectsAndKeys:statusNumb, @"value", freshAuthorityDate, @"date", nil];
800 [healthKitNutritionAuthorityDict setObject:freshAuthorityDict forKey:hkQtypeString];
803 case HKAuthorizationStatusNotDetermined:
807 case HKAuthorizationStatusSharingDenied:
811 case HKAuthorizationStatusSharingAuthorized:
817 NSLog(
@"LocalData.validateHealthKitAuthority: notDetermined: %d itemDenied: %d itemAuthorized: %d", notDetermined, itemDenied, itemAuthorized);
821 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
823 [userDefaults setObject:healthKitNutritionAuthorityDict forKey:healthKitAuthorityKey];
825 [userDefaults synchronize];
834 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
836 [userDefaults synchronize];
838 NSDictionary *hkUd = [userDefaults dictionaryForKey:healthKitAuthorityKey];
840 NSLog(
@"LocalData.getHealthKitAuthorityFromUserDefaults: prior on-board count: %ld user-defaults: %@", (
unsigned long)[
healthKitNutritionAuthorityDict count], hkUd);
842 Boolean hkDictionaryEmpty = (0 == [healthKitNutritionAuthorityDict count]);
843 if (0 < [hkUd count]) {
847 NSDictionary *authorityInfo;
850 if (!hkDictionaryEmpty) {
852 authorityInfo = [healthKitNutritionAuthorityDict objectForKey:hkQtypeString];
853 statNumb = [authorityInfo objectForKey:@"@value"];
861 NSMutableDictionary* userDefInfoDict = [hkUd objectForKey:hkQtypeString];
862 NSNumber *udAuthNumb = [userDefInfoDict objectForKey:@"value"];
866 if ((nil != udAuthNumb) && (nil != statNumb) && (![udAuthNumb isEqualToNumber:statNumb])) {
867 NSLog(
@"LocalData.getHealthKitAuthorityFromUserDefaults: type: %@ updated: new auth: %@", hkQtypeString, udAuthNumb);
868 NSDate *authChangeDate = [NSDate dateWithTimeIntervalSinceNow:0];
869 [userDefInfoDict setObject:authChangeDate forKey:@"date"];
877 if (userDefInfoDict) {
880 [healthKitNutritionAuthorityDict setObject:userDefInfoDict forKey:hkQtypeString];
884 NSLog(
@"LocalData.getHealthKitAuthorityFromUserDefaults: no %@ dictionary entries in user defaults",
healthKitAuthorityKey);
887 - (NSNumber *) askAgain: (HKQuantityType *) quantityType
889 __block NSNumber *statusFlag = [NSNumber numberWithBool:NO];
890 NSSet *writeDataTypes = [NSSet setWithObjects:quantityType, nil];
891 NSSet *readDataTypes = [[NSSet alloc] init];
892 [
self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) {
894 NSLog(@"Z5LocalDataController.askAgain: The error was: %@", error);
897 NSLog(@"Z5LocalDataController.askAgain: authorization success");
898 statusFlag = [NSNumber numberWithBool:YES];
901 dispatch_async(dispatch_get_main_queue(), ^{
902 [
self->healthConnectDelegate updateToAuthorizationOK];
913 #pragma mark - HealthKit Permissions 918 __block NSMutableSet *retSet = [[NSMutableSet alloc] init];
920 [healthKitNutritionAuthorityDict enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
921 NSString *keyString = (NSString *)key;
922 NSNumber *objectNumber = (NSNumber *)object;
923 Boolean objBoolean = [objectNumber boolValue];
925 HKQuantityType *keyHkQtype = [HKObjectType quantityTypeForIdentifier:keyString];
926 [retSet addObject:keyHkQtype];
930 if (0 == [retSet count]) {
931 HKQuantityType *sodiumType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDietarySodium];
932 [retSet addObject:sodiumType];
938 __block NSMutableArray *retArray = [[NSMutableArray alloc] init];
939 [healthKitNutritionAuthorityDict enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
940 NSString *keyString = (NSString *)key;
941 NSNumber *objectNumber = (NSNumber *)object;
942 Boolean objBoolean = [objectNumber boolValue];
944 HKQuantityType *keyHkQtype = [HKObjectType quantityTypeForIdentifier:keyString];
945 [retArray addObject:keyHkQtype];
952 NSMutableArray<HKQuantityType *> *returHkArray = [[NSMutableArray alloc] init];
955 HKQuantityType *hkQtype = [HKObjectType quantityTypeForIdentifier:param];
956 [returHkArray addObject:hkQtype];
1013 - (NSNumber *) checkTypeAuthorization: (HKQuantityType *) quantityType
1017 NSString *hkQtypeString = quantityType.description;
1019 NSMutableDictionary *knownAuthStatusDict = [healthKitNutritionAuthorityDict objectForKey:hkQtypeString];
1020 NSNumber *knownAuthStatus = [knownAuthStatusDict objectForKey:@"value"];
1021 NSDate *knownAuthStatusDate = [knownAuthStatusDict objectForKey:@"date"];
1022 if (doDebug) NSLog(
@"LocalData.checkTypeAuthorization: knownAuthStatus: for %@: %@", hkQtypeString, knownAuthStatus);
1024 NSInteger knownAuthStatusInt = [knownAuthStatus integerValue];
1025 if (doDebug) NSLog(
@"LocalData.checkTypeAuthorization: type: %@:previous auth: %ld, date: %@", hkQtypeString, (
long)[knownAuthStatus integerValue], [knownAuthStatusDate description]);
1028 NSInteger authStatus = [
self.healthStore authorizationStatusForType:quantityType];
1030 if (authStatus != knownAuthStatusInt) {
1031 if (doDebug) NSLog(
@"LocalData.checkTypeAuthorization: AUTH CHANGE: was %ld now %ld", (
long)knownAuthStatusInt, (
long)authStatus);
1033 switch (authStatus) {
1034 case HKAuthorizationStatusSharingAuthorized:
1035 if (doDebug) NSLog(
@"Z5LocalDataController.checkTypeAuthorization: %@ HKAuthorizationStatusSharingAuthorized", [quantityType description]);
1037 case HKAuthorizationStatusNotDetermined:
1038 if (doDebug) NSLog(
@"Z5LocalDataController.checkTypeAuthorization: %@ HKAuthorizationStatusNotDetermined", [quantityType description]);
1040 case HKAuthorizationStatusSharingDenied:
1041 if (doDebug) NSLog(
@"Z5LocalDataController.checkTypeAuthorization: %@ HKAuthorizationStatusSharingDenied", [quantityType description]);
1043 case HKErrorAuthorizationDenied:
1044 if (doDebug) NSLog(
@"Z5LocalDataController.checkTypeAuthorization: %@ HKErrorAuthorizationDenied", [quantityType description]);
1046 case HKErrorAuthorizationNotDetermined:
1047 if (doDebug) NSLog(
@"Z5LocalDataController.checkTypeAuthorization: %@ HKErrorAuthorizationNotDetermined", [quantityType description]);
1050 NSNumber *ret = [NSNumber numberWithInteger:authStatus];
1062 - (NSMutableArray<NSMutableDictionary *> *) annotateAuthority:(NSArray *)componentArray
1078 NSMutableArray *ret = [[NSMutableArray alloc] init];
1080 for (NSDictionary *component in componentArray) {
1082 if (componentType) {
1083 NSString *fullyQualifiedCompoName = [@"HKQuantityTypeIdentifierDietary" stringByAppendingString:componentType];
1084 HKQuantityType *rowQuantityType = [HKObjectType quantityTypeForIdentifier:fullyQualifiedCompoName];
1088 NSMutableDictionary *withAuthMarkDict = [[NSMutableDictionary alloc] initWithDictionary:component];
1091 NSDate *authorityDate = [NSDate dateWithTimeIntervalSinceNow:0];
1095 [ret addObject:withAuthMarkDict];
1101 #pragma mark - Writing HealthKit Data 1102 - (Boolean) goHealthData:(NSArray<NSDictionary *> *) parametersForHK forDelegate: (
id<Z5HealthConnectionProtocol>)jingo
1104 healthConnectDelegate = jingo;
1106 Boolean ret = [HKHealthStore isHealthDataAvailable];
1108 NSLog(
@"LocalData.goHealthData: addMenuItemOnToday: HKHealthStore is available");
1111 for (NSDictionary *datum in parametersForHK) {
1112 NSLog(
@"LocalData.goHealthData: datum: %@", datum);
1115 NSString *hkTypeStr = [@"HKQuantityTypeIdentifierDietary" stringByAppendingString:nutriType];
1116 HKQuantityType *hkType = [HKQuantityType quantityTypeForIdentifier:hkTypeStr];
1117 HKUnit *massUnit = [HKUnit unitFromString:@"g"];
1118 HKUnit *energyUnit = [HKUnit unitFromString:@"cal"];
1120 HKUnit *hkUnit = nil;
1121 NSString *nutriValue = [datum objectForKey:componentValueKey];
1122 NSLog(
@"LocalData.goHealthData: nutriValue: %@", nutriValue);
1123 NSArray<NSString *> *pieces = [nutriValue componentsSeparatedByString:@" "];
1125 float quantityScalar = [pieces[0] floatValue];
1126 if ([hkType isCompatibleWithUnit:energyUnit])
1128 if ([
@"cal" isEqualToString:pieces[1]]) {
1129 HKMetricPrefix microPrefix = HKMetricPrefixNone;
1130 hkUnit = [HKUnit jouleUnitWithMetricPrefix:microPrefix];
1132 }
else if ([hkType isCompatibleWithUnit:massUnit]){
1133 if ([
@"mcg" isEqualToString:pieces[1]]) {
1134 HKMetricPrefix microPrefix = HKMetricPrefixMicro;
1135 hkUnit = [HKUnit gramUnitWithMetricPrefix:microPrefix];
1136 }
else if ([
@"mg" isEqualToString:pieces[1]]) {
1137 HKMetricPrefix milliPrefix = HKMetricPrefixMilli;
1138 hkUnit = [HKUnit gramUnitWithMetricPrefix:milliPrefix];
1141 HKQuantity *hkQuantity = [HKQuantity quantityWithUnit:hkUnit doubleValue:quantityScalar];
1143 NSDictionary *opQueueIn = [[NSDictionary alloc] initWithObjectsAndKeys:hkType, @"HKtype", hkQuantity, @"HKquantity", nil];
1144 [healthKitOpQueue addOperation:[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(tryHealthStore:) object:opQueueIn]];
1147 [healthKitOpQueue waitUntilAllOperationsAreFinished];
1148 NSLog(
@"LocalData.goHealthData: done waiting");
1153 - (void) tryHealthStore:(
id)arg
1155 NSDictionary *inputVars = arg;
1157 HKQuantityType *hkType = [inputVars objectForKey:@"HKtype"];
1158 HKQuantity *hkQuantity = [inputVars objectForKey:@"HKquantity"];
1162 - (void) saveQuantityToHealthStore:(HKQuantityType *)quantityType amount:(HKQuantity *)quantityAmount
1164 NSDate *now = [NSDate date];
1166 HKQuantitySample *quantitySample = [HKQuantitySample quantitySampleWithType:quantityType quantity:quantityAmount startDate:now endDate:now];
1167 NSInteger authStatus = [
self.healthStore authorizationStatusForType:quantityType];
1168 NSString *quantityAuthority =
@"none";
1169 switch (authStatus) {
1170 case HKAuthorizationStatusSharingAuthorized:
1171 NSLog(
@"Z5LocalDataController.saveQuantityToHealthStore: HKAuthorizationStatusSharingAuthorized");
1172 quantityAuthority =
@"HKAuthorizationStatusSharingAuthorized";
1174 case HKAuthorizationStatusNotDetermined:
1175 NSLog(
@"Z5LocalDataController.saveQuantityToHealthStore: HKAuthorizationStatusNotDetermined");
1176 quantityAuthority =
@"HKAuthorizationStatusNotDetermined";
1178 case HKAuthorizationStatusSharingDenied:
1179 NSLog(
@"Z5LocalDataController.saveQuantityToHealthStore: HKAuthorizationStatusSharingDenied");
1180 quantityAuthority =
@"HKAuthorizationStatusSharingDenied";
1182 case HKErrorAuthorizationDenied:
1183 NSLog(
@"Z5LocalDataController.saveQuantityToHealthStore: HKErrorAuthorizationDenied");
1184 quantityAuthority =
@"HKErrorAuthorizationDenied";
1186 case HKErrorAuthorizationNotDetermined:
1187 NSLog(
@"Z5LocalDataController.saveQuantityToHealthStore: HKErrorAuthorizationNotDetermined");
1188 quantityAuthority =
@"HKErrorAuthorizationNotDetermined";
1192 NSLog(
@"Z5LocalDataController.saveQuantityToHealthStore: type: %@ authority: %@ quantitySample: %@", quantityType, quantityAuthority, quantitySample);
1194 switch (authStatus) {
1195 case HKAuthorizationStatusSharingAuthorized:
1197 [
self.healthStore saveObject:quantitySample withCompletion:^(BOOL success, NSError *error) {
1199 NSLog(@"An error occured saving the quantity sample %@. In your app, try to handle this gracefully. The error was: %@.", quantitySample, error);
1201 NSLog(@"Z5LocalDataController.saveQuantityToHealthStore: ERR code: %ld", (long)error.code);
1204 NSLog(@"Z5LocalDataController.saveQuantityToHealthStore: success with %@", quantityType);
1232 + (HKQuantity *) hkQuantityForString: (NSString *) quantityDescript
1234 NSArray<NSString *> *pieces = [quantityDescript componentsSeparatedByString:@" "];
1235 HKUnit *hkUnit = nil;
1236 float quantityScalar = [pieces[0] floatValue];
1239 if ([
@"mcg" isEqualToString:pieces[1]]) {
1240 HKMetricPrefix microPrefix = HKMetricPrefixMicro;
1241 hkUnit = [HKUnit gramUnitWithMetricPrefix:microPrefix];
1242 }
else if ([
@"mg" isEqualToString:pieces[1]]) {
1243 HKMetricPrefix milliPrefix = HKMetricPrefixMilli;
1244 hkUnit = [HKUnit gramUnitWithMetricPrefix:milliPrefix];
1246 HKQuantity *hkQuantity = [HKQuantity quantityWithUnit:hkUnit doubleValue:quantityScalar];
1253 #pragma mark - Email Credentials / User Defaults 1257 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
1264 [userDefaults synchronize];
1276 #pragma mark - EmailMessage Data 1302 - (
EmailMessage *) findOrCreateEmailMessageWithFileIdentification: (NSString *)googlefileid
1304 NSLog(
@"LocalData.findEmailMessageWithFileIdentification");
1310 - (
EmailMessage *) findEmailMessageWithFileIdentification:(NSString *) googlefileid
1318 ret = [msgs objectAtIndex:0];
1326 NSEntityDescription *entityDescription = [NSEntityDescription
1327 entityForName:@"EmailMessage" inManagedObjectContext:moc];
1328 NSFetchRequest *request = [[NSFetchRequest alloc] init];
1329 [request setEntity:entityDescription];
1332 NSArray *objects = [
self.managedObjectContext executeFetchRequest:request error:&error];
1351 - (Boolean) deleteEmailMessageWithFileIdentification:(NSString *)googlefileid
1358 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
1360 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES];
1361 NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
1362 [fetchRequest setSortDescriptors:sortDescriptors];
1364 NSFetchedResultsController *controller = [[NSFetchedResultsController alloc]
1365 initWithFetchRequest:fetchRequest
1366 managedObjectContext:context
1367 sectionNameKeyPath:nil
1368 cacheName:@"TodaysMenu"];
1370 BOOL success = [controller performFetch:&error];
1375 #pragma mark - Write Defaults 1379 NSNumber *galleryChoice = [NSNumber numberWithInt:1];
1381 for (NSManagedObject *
menuItem in objects) {
1383 NSLog(
@"RemoteData.fillMenuItemList: menuItem into list: %@", [dbMenuItem name]);
1388 if (!focusMenuItem) {
1389 NSLog(
@"Z5LocalData.putMenuItemOnToday: FAIL, nil input");
1392 if (!_todaysMenuItems) {
1393 _todaysMenuItems = [[NSMutableArray alloc] init];
1394 NSLog(
@"Z5LocalData.putMenuItemOnToday: todays-menu-items array created");
1396 [_todaysMenuItems addObject:focusMenuItem];
1400 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
1402 NSMutableArray *menuItemKeys = [[NSMutableArray alloc] init];
1403 for (NSManagedObject *
menuItem in _todaysMenuItems) {
1405 [menuItemKeys addObject:[dbMenuItem
randomkey]];
1408 [userDefaults setObject:menuItemKeys forKey:proposedMenuItemList];
1410 [userDefaults synchronize];
1418 NSLog(
@"Z5LocalData.clearTodaysMenuItems");
1419 [_todaysMenuItems removeAllObjects];
1421 - (NSArray<NSDictionary *> *) mealComponents: (
Meal *)meal
1423 NSMutableArray<NSDictionary *> *totals = [[NSMutableArray alloc] init];
1424 for (
MenuItem *mItem in [meal containedItem]) {
1427 NSArray<NSDictionary *> *
usdaParameterArray = [currentParameters objectForKey:@"usdaNumbers"];
1429 [totals addObjectsFromArray:usdaParameterArray];
1435 NSMutableArray<NSDictionary *> *totals = [[NSMutableArray alloc] init];
1440 if (currentParameters) {
1441 NSArray<NSDictionary *> *
usdaParameterArray = [currentParameters objectForKey:@"usdaNumbers"];
1442 [totals addObjectsFromArray:usdaParameterArray];
1444 NSLog(
@"LocalData.todaysMenuComponents: no parameters for %@", mItem.name);
1449 NSArray<NSMutableDictionary*> *annotatedArray;
1450 if (0 < [totals count]) {
1452 localDataController]
1453 annotateAuthority:totals];
1454 for (NSDictionary *entr in annotatedArray) {
1458 double quantDbl = 0.0;
1459 if ([quant isCompatibleWithUnit:[HKUnit gramUnit]]) {
1460 quantDbl = [quant doubleValueForUnit:[HKUnit gramUnit]];
1461 }
else if ([quant isCompatibleWithUnit:[HKUnit jouleUnit]]) {
1462 quantDbl = [quant doubleValueForUnit:[HKUnit jouleUnitWithMetricPrefix:HKMetricPrefixMicro]];
1465 Boolean authFlag = [ authority boolValue];
1467 if (0.0 < quantDbl) {
1475 NSLog(
@"LocalData.todaysMenuComponents: no quantity for %@", name);
1479 NSLog(
@"LocalData.todaysMenuComponents: no totals for todays menu");
1482 return annotatedArray;
1487 for (NSManagedObject *emailMessage in emObjects) {
1489 NSLog(
@"LocalData.logEmailMessageAndEmailMessageList: menuItem into list: %@", [dbEmailMessage subject]);
1492 NSNumber *galleryChoice = [NSNumber numberWithInt:1];
1494 for (NSManagedObject *
menuItem in objects) {
1496 NSLog(
@"LocalData.logEmailMessageAndMenuItemList: menuItem into list: %@", [dbMenuItem name]);
1501 #pragma mark - Read Defaults 1507 NSUserDefaults *udef = [NSUserDefaults standardUserDefaults];
1509 NSLog(
@"LocalData.getBestAvailableUserDefaultMethod: udef: %@", udef);
1511 NSArray *theaterMenuArray = [udef arrayForKey:healthDataAuthority];
1513 NSDictionary *theaterItemDictionary = [udef dictionaryForKey:showTheaterItem];
1515 NSString *theaterVersion1 = [udef stringForKey:showTheaterVersion1];
1517 if (theaterMenuArray) {
1520 }
else if (theaterItemDictionary) {
1523 }
else if (theaterVersion1) {
1528 NSLog(
@"LocalData.getBestAvailableUserDefaultMethod: ret: %d", ret);
1541 NSUserDefaults *udef = [NSUserDefaults standardUserDefaults];
1542 NSArray *proposedMenuItemArray = [udef arrayForKey:proposedMenuItemList];
1544 if (!_todaysMenuItems) {
1545 _todaysMenuItems = [[NSMutableArray alloc] init];
1548 if (proposedMenuItemArray) {
1551 for (NSString *menuItemRandomkey in proposedMenuItemArray) {
1553 [_todaysMenuItems addObject:dbMenuItem];
1558 NSMutableArray *ret = nil;
1665 #pragma mark - Application's Documents directory 1672 return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSString * componentHKComponentKey()
UIColor * menuHeaderBackground()
Boolean goHealthData:forDelegate:(NSArray< NSDictionary * > *parametersForHK, [forDelegate] id< Z5HealthConnectionProtocol > jingo)
NSString * produceRandomkey()
int getBestAvailableUserDefaultMethod()
UIColor * wheatBackground
void examineDbMenuItems()
UIColor * menuContentsBackground
NSManagedObjectModel * managedObjectModel
void initializeTodaysMeal()
UIColor * healthKitParamSharedColor
NSArray< HKQuantityType * > * allHkTypes()
NSArray< MenuItem * > * retrieveAllMenuItems:(NSNumber *galleryNo)
NSString * componentNameKey()
NSString * showTheaterMenu
Boolean deleteEmailMessageWithFileIdentification:context:(NSString *googlefileid, [context] NSManagedObjectContext *moc)
void logEmailMessageAndMenuItemList()
NSString * showCurrentScene
NSInteger nutritionTypeCount
NSString * componentAuthorityDateKey()
UIColor * menuHeaderBackground
void removeTodaysMealFromDatabase()
NSArray * retrieveAllMealsForGallery:context:(NSNumber *mealGallery, [context] NSManagedObjectContext *moc)
static NSString * componentValueKey
NSArray< NSDictionary * > * todaysMenuComponents()
instancetype sharedInstance()
NSArray< Meal * > * retrieveAllMeals:(NSNumber *galleryNumber)
NSInteger getPrevGalleryPositionIdx()
NSInteger getNextGalleryPositionIdx()
NSString * healthKitAuthorityKey
void putHealthKitAuthorityInUserDefaults()
NSString * healthDataAuthority
UIColor * panelBackgroundColor()
Boolean removeMealWithRandomkey:(NSString *removeKey)
NSString * healthkitNutritionAuthorized
UIColor * healthKitParamNotQueried
NSPersistentStoreCoordinator * persistentStoreCoordinator
static NSString * componentAuthorityKey
NSMutableArray * availableNutritionParamArray
static NSString * componentNameKey
void getHealthKitAuthorityFromUserDefaults()
void initNutritionTypes()
NSString * proposedMenuItemList
NSString * componentSampleKey()
NSOperationQueue * healthKitOpQueue
static NSString * componentSampleKey
NSSet * dataTypesToWrite()
NSArray< Meal * > * findMealsByMonth:context:(NSDate *nowdate, [context] NSManagedObjectContext *moc)
NSMutableArray * createTodaysMenuFromUserDefaults()
void saveQuantityToHealthStore:amount:(HKQuantityType *quantityType, [amount] HKQuantity *quantityAmount)
static NSString * componentAuthorityDateKey
UIColor * menuContentsBackground()
HKQuantity * hkQuantityForString:(NSString *quantityDescript)
NSMutableArray * establishNutritionParameters()
NSString * showTheaterItem
NSString * componentValueKey()
NSDictionary * jsonForUsdaNumbersInMenuItem:(MenuItem *menuItem)
NSManagedObjectContext * managedObjectContext
NSString * healthkitNutritionKey
void deleteMealsByMonth:context:(NSDate *nowdate, [context] NSManagedObjectContext *moc)
NSString * componentAuthorityKey()
EmailMessage * findOrCreateEmailMessageWithFileIdentification:context:(NSString *googlefileid, [context] NSManagedObjectContext *moc)
void putTodaysMenuInUserDefaults()
MenuItem * findMenuItemWithRandomkey:(NSString *randomkey)
NSNumber * checkTypeAuthorization:(HKQuantityType *quantityType)
NSArray< HKQuantityType * > * typesForWriting()
NSArray< Meal * > * findOrCreateMealWithDate:(NSDate *findDate)
Singleton interface to both core and remote data sources.
UIColor * wheatBackground()
void validateHealthKitAuthority()
static NSString * componentHKComponentKey
void deleteMealByRandomkey:context:(NSString *deleteKey, [context] NSManagedObjectContext *moc)
HKHealthStore * healthStore
NSArray< Meal * > * findOrCreateMealWithDate:context:(NSDate *findDate, [context] NSManagedObjectContext *moc)
NSMutableDictionary * healthKitNutritionAuthorityDict
NSMutableArray * usdaParameterArray
void putCredentialsInUserDefaults()
HKQuantityTypeIdentifier nutritionTypes[40]
NSString * healthkitNutritionValidated
UIColor * panelBackgroundColor
NSRange currentMenuItemGalleryPositions
NSArray * retrieveAllEmailMessages()
UIColor * healthKitParamDeniedAuthColor
void fetchCredentialsFromUserDefaults()
NSArray< Meal * > * findMealsWithDate:context:(NSDate *findDate, [context] NSManagedObjectContext *moc)
NSURL * applicationDocumentsDirectory()
NSString * showTheaterVersion1
NSString * unitsForParameter:(NSString *paramKeyStr)
NSMutableArray< MenuItem * > * todaysMenuItems
void clearTodaysMenuItems()
NSArray * emailMessageWithFileid:context:(NSString *googlefileid, [context] NSManagedObjectContext *moc)