From 3bef34f17740583ed92057f2d4a5dbd12716b5ae Mon Sep 17 00:00:00 2001 From: Brent Hargrave Date: Mon, 4 May 2015 15:45:44 -0400 Subject: [PATCH] rename library to Granola --- {doc => Docs}/hkobject_type_coverage.md | 2 +- .../project.pbxproj | 52 ++--- .../xcschemes/Granola-Example.xcscheme} | 30 +-- .../contents.xcworkspacedata | 2 +- Example/Podfile | 13 +- Example/Podfile.lock | 27 +-- Example/Tests/OMHSerializerTests.m | 87 +++---- Granola.podspec | 18 ++ HealthKitIO.podspec | 39 ---- LICENSE | 220 ++++++++++++++++-- Pod/Classes/NSDate+RFC3339.h | 3 + Pod/Classes/NSDate+RFC3339.m | 23 +- Pod/Classes/OMHError.m | 2 +- Pod/Classes/OMHSerializer.h | 5 +- Pod/Classes/OMHSerializer.m | 64 +++-- README.md | 101 ++++---- 16 files changed, 437 insertions(+), 251 deletions(-) rename {doc => Docs}/hkobject_type_coverage.md (99%) rename Example/{HealthKitIO.xcodeproj => Granola.xcodeproj}/project.pbxproj (85%) rename Example/{HealthKitIO.xcodeproj/xcshareddata/xcschemes/HealthKitIO-Example.xcscheme => Granola.xcodeproj/xcshareddata/xcschemes/Granola-Example.xcscheme} (77%) rename Example/{HealthKitIO.xcworkspace => Granola.xcworkspace}/contents.xcworkspacedata (79%) create mode 100644 Granola.podspec delete mode 100644 HealthKitIO.podspec diff --git a/doc/hkobject_type_coverage.md b/Docs/hkobject_type_coverage.md similarity index 99% rename from doc/hkobject_type_coverage.md rename to Docs/hkobject_type_coverage.md index f266d1e..7107e26 100644 --- a/doc/hkobject_type_coverage.md +++ b/Docs/hkobject_type_coverage.md @@ -1,6 +1,6 @@ ## HKObjectType Coverage -|HKObject type|HealthKitIO| +|HKObject type|Granola| |-------------|:---------:| |*__Nutrition Identifiers__*|| |HKQuantityTypeIdentifierDietaryBiotin| | diff --git a/Example/HealthKitIO.xcodeproj/project.pbxproj b/Example/Granola.xcodeproj/project.pbxproj similarity index 85% rename from Example/HealthKitIO.xcodeproj/project.pbxproj rename to Example/Granola.xcodeproj/project.pbxproj index 35dacf4..ed4fe49 100644 --- a/Example/HealthKitIO.xcodeproj/project.pbxproj +++ b/Example/Granola.xcodeproj/project.pbxproj @@ -15,18 +15,18 @@ 9E272AB11ADEFF1B007DE4ED /* OMHSampleFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E272AB01ADEFF1B007DE4ED /* OMHSampleFactory.m */; }; 9E272AB41ADF523F007DE4ED /* OMHSchemaStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E272AB31ADF523F007DE4ED /* OMHSchemaStore.m */; }; 9ECA505C1AD60A3000E367CA /* schema in Resources */ = {isa = PBXBuildFile; fileRef = 9ECA505B1AD60A3000E367CA /* schema */; }; - F8FEF4241A43B7BFE271ADD7 /* libPods-HealthKitIO.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CABD26178AD457AEB783167 /* libPods-HealthKitIO.a */; }; + F8FEF4241A43B7BFE271ADD7 /* libPods-Granola.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CABD26178AD457AEB783167 /* libPods-Granola.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 0713970833C99FFE3A26765F /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; - 0CABD26178AD457AEB783167 /* libPods-HealthKitIO.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HealthKitIO.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1497BA18A434AE1495648DE8 /* HealthKitIO.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = HealthKitIO.podspec; path = ../HealthKitIO.podspec; sourceTree = ""; }; - 6003F58A195388D20070C39A /* HealthKitIO.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HealthKitIO.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CABD26178AD457AEB783167 /* libPods-Granola.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Granola.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1497BA18A434AE1495648DE8 /* Granola.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Granola.podspec; path = ../Granola.podspec; sourceTree = ""; }; + 6003F58A195388D20070C39A /* Granola.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Granola.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 6003F5AE195388D20070C39A /* HealthKitIO.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HealthKitIO.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6003F5AE195388D20070C39A /* Granola.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Granola.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -38,9 +38,9 @@ 9E272AB31ADF523F007DE4ED /* OMHSchemaStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OMHSchemaStore.m; sourceTree = ""; }; 9ECA505B1AD60A3000E367CA /* schema */ = {isa = PBXFileReference; lastKnownFileType = folder; name = schema; path = "omh-schemas/schema"; sourceTree = ""; }; 9EDEA5811ADB0B5200D3F174 /* HKObject+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HKObject+Private.h"; sourceTree = ""; }; - AD7D73655EC87F9772FA4779 /* Pods-HealthKitIO.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HealthKitIO.debug.xcconfig"; path = "Pods/Target Support Files/Pods-HealthKitIO/Pods-HealthKitIO.debug.xcconfig"; sourceTree = ""; }; + AD7D73655EC87F9772FA4779 /* Pods-Granola.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Granola.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Granola/Pods-Granola.debug.xcconfig"; sourceTree = ""; }; EF857A4BFD07184BC663D020 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; - F9F510F403C68D61B5084DE9 /* Pods-HealthKitIO.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HealthKitIO.release.xcconfig"; path = "Pods/Target Support Files/Pods-HealthKitIO/Pods-HealthKitIO.release.xcconfig"; sourceTree = ""; }; + F9F510F403C68D61B5084DE9 /* Pods-Granola.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Granola.release.xcconfig"; path = "Pods/Target Support Files/Pods-Granola/Pods-Granola.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -51,7 +51,7 @@ 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, - F8FEF4241A43B7BFE271ADD7 /* libPods-HealthKitIO.a in Frameworks */, + F8FEF4241A43B7BFE271ADD7 /* libPods-Granola.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -61,8 +61,8 @@ 3CBAC3C90B6EE47B545DBAFB /* Pods */ = { isa = PBXGroup; children = ( - AD7D73655EC87F9772FA4779 /* Pods-HealthKitIO.debug.xcconfig */, - F9F510F403C68D61B5084DE9 /* Pods-HealthKitIO.release.xcconfig */, + AD7D73655EC87F9772FA4779 /* Pods-Granola.debug.xcconfig */, + F9F510F403C68D61B5084DE9 /* Pods-Granola.release.xcconfig */, ); name = Pods; sourceTree = ""; @@ -81,8 +81,8 @@ 6003F58B195388D20070C39A /* Products */ = { isa = PBXGroup; children = ( - 6003F58A195388D20070C39A /* HealthKitIO.app */, - 6003F5AE195388D20070C39A /* HealthKitIO.xctest */, + 6003F58A195388D20070C39A /* Granola.app */, + 6003F5AE195388D20070C39A /* Granola.xctest */, ); name = Products; sourceTree = ""; @@ -94,7 +94,7 @@ 6003F58F195388D20070C39A /* CoreGraphics.framework */, 6003F591195388D20070C39A /* UIKit.framework */, 6003F5AF195388D20070C39A /* XCTest.framework */, - 0CABD26178AD457AEB783167 /* libPods-HealthKitIO.a */, + 0CABD26178AD457AEB783167 /* libPods-Granola.a */, ); name = Frameworks; sourceTree = ""; @@ -127,7 +127,7 @@ 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { isa = PBXGroup; children = ( - 1497BA18A434AE1495648DE8 /* HealthKitIO.podspec */, + 1497BA18A434AE1495648DE8 /* Granola.podspec */, EF857A4BFD07184BC663D020 /* README.md */, 0713970833C99FFE3A26765F /* LICENSE */, ); @@ -137,9 +137,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 6003F5AD195388D20070C39A /* HealthKitIO */ = { + 6003F5AD195388D20070C39A /* Granola */ = { isa = PBXNativeTarget; - buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "HealthKitIO" */; + buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Granola" */; buildPhases = ( 4C80BEBFD91B74FEFF48262F /* Check Pods Manifest.lock */, 6003F5AA195388D20070C39A /* Sources */, @@ -151,9 +151,9 @@ ); dependencies = ( ); - name = HealthKitIO; - productName = HealthKitIOTests; - productReference = 6003F5AE195388D20070C39A /* HealthKitIO.xctest */; + name = Granola; + productName = GranolaTests; + productReference = 6003F5AE195388D20070C39A /* Granola.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -171,7 +171,7 @@ }; }; }; - buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "HealthKitIO" */; + buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "Granola" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -184,7 +184,7 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 6003F5AD195388D20070C39A /* HealthKitIO */, + 6003F5AD195388D20070C39A /* Granola */, ); }; /* End PBXProject section */ @@ -229,7 +229,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HealthKitIO/Pods-HealthKitIO-resources.sh\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Granola/Pods-Granola-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -333,7 +333,7 @@ }; 6003F5C3195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = AD7D73655EC87F9772FA4779 /* Pods-HealthKitIO.debug.xcconfig */; + baseConfigurationReference = AD7D73655EC87F9772FA4779 /* Pods-Granola.debug.xcconfig */; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", @@ -355,7 +355,7 @@ }; 6003F5C4195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F9F510F403C68D61B5084DE9 /* Pods-HealthKitIO.release.xcconfig */; + baseConfigurationReference = F9F510F403C68D61B5084DE9 /* Pods-Granola.release.xcconfig */; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", @@ -374,7 +374,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 6003F585195388D10070C39A /* Build configuration list for PBXProject "HealthKitIO" */ = { + 6003F585195388D10070C39A /* Build configuration list for PBXProject "Granola" */ = { isa = XCConfigurationList; buildConfigurations = ( 6003F5BD195388D20070C39A /* Debug */, @@ -383,7 +383,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "HealthKitIO" */ = { + 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Granola" */ = { isa = XCConfigurationList; buildConfigurations = ( 6003F5C3195388D20070C39A /* Debug */, diff --git a/Example/HealthKitIO.xcodeproj/xcshareddata/xcschemes/HealthKitIO-Example.xcscheme b/Example/Granola.xcodeproj/xcshareddata/xcschemes/Granola-Example.xcscheme similarity index 77% rename from Example/HealthKitIO.xcodeproj/xcshareddata/xcschemes/HealthKitIO-Example.xcscheme rename to Example/Granola.xcodeproj/xcshareddata/xcschemes/Granola-Example.xcscheme index f7c607b..cfaca45 100644 --- a/Example/HealthKitIO.xcodeproj/xcshareddata/xcschemes/HealthKitIO-Example.xcscheme +++ b/Example/Granola.xcodeproj/xcshareddata/xcschemes/Granola-Example.xcscheme @@ -15,9 +15,9 @@ + BuildableName = "Granola.xctest" + BlueprintName = "Granola" + ReferencedContainer = "container:Granola.xcodeproj"> @@ -33,9 +33,9 @@ + BuildableName = "Granola.xctest" + BlueprintName = "Granola" + ReferencedContainer = "container:Granola.xcodeproj"> @@ -43,9 +43,9 @@ + BuildableName = "Granola.xctest" + BlueprintName = "Granola" + ReferencedContainer = "container:Granola.xcodeproj"> @@ -63,9 +63,9 @@ + BuildableName = "Granola.xctest" + BlueprintName = "Granola" + ReferencedContainer = "container:Granola.xcodeproj"> @@ -82,9 +82,9 @@ + BuildableName = "Granola.xctest" + BlueprintName = "Granola" + ReferencedContainer = "container:Granola.xcodeproj"> diff --git a/Example/HealthKitIO.xcworkspace/contents.xcworkspacedata b/Example/Granola.xcworkspace/contents.xcworkspacedata similarity index 79% rename from Example/HealthKitIO.xcworkspace/contents.xcworkspacedata rename to Example/Granola.xcworkspace/contents.xcworkspacedata index 2a2b7bd..96c79e1 100644 --- a/Example/HealthKitIO.xcworkspace/contents.xcworkspacedata +++ b/Example/Granola.xcworkspace/contents.xcworkspacedata @@ -2,7 +2,7 @@ + location = "group:Granola.xcodeproj"> diff --git a/Example/Podfile b/Example/Podfile index 0caf51b..1063272 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,11 +1,10 @@ source 'https://github.com/CocoaPods/Specs.git' +target 'Granola', :exclusive => true do + pod "Granola", :path => "../" -target 'HealthKitIO', :exclusive => true do - pod "HealthKitIO", :path => "../" - - pod 'Specta' - pod 'Expecta' - pod 'NSObject-Tap' - pod 'VVJSONSchemaValidation' + pod 'Specta', '~> 1.0' + pod 'Expecta', '~> 1.0' + pod 'VVJSONSchemaValidation', '~> 1.3' end + diff --git a/Example/Podfile.lock b/Example/Podfile.lock index b6cf58b..c8470d6 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,29 +1,26 @@ PODS: - - Expecta (0.4.0) - - HealthKitIO (0.1.0): + - Expecta (1.0.0) + - Granola (0.1.0): - ObjectiveSugar (~> 1.1) - - NSObject-Tap (1.0.1) - ObjectiveSugar (1.1.0) - - Specta (0.5.0) + - Specta (1.0.0) - VVJSONSchemaValidation (1.3.0) DEPENDENCIES: - - Expecta - - HealthKitIO (from `../`) - - NSObject-Tap - - Specta - - VVJSONSchemaValidation + - Expecta (~> 1.0) + - Granola (from `../`) + - Specta (~> 1.0) + - VVJSONSchemaValidation (~> 1.3) EXTERNAL SOURCES: - HealthKitIO: + Granola: :path: "../" SPEC CHECKSUMS: - Expecta: 392a6b5bfb9f4097e47dd8064d9b732079490332 - HealthKitIO: 4b1a0b43a5e1b0d479336243a7bb40197a588522 - NSObject-Tap: 07b174cf61d27b1b56384300d4ca2220853ab43b + Expecta: 32604574add2c46a36f8d2f716b6c5736eb75024 + Granola: 5c4834fe825ae1ab57e6913749213f7e504cbebb ObjectiveSugar: a6a25f23d657c19df0a0b972466d5b5ca9f5295c - Specta: eb90708ed77569bbda089f8ead10bb99b8e9489e + Specta: 96fe05fe5c7348b5223f85e862904f6e832abb14 VVJSONSchemaValidation: a384962161691d152c02464e61a86b4014f27d7c -COCOAPODS: 0.36.4 +COCOAPODS: 0.37.1 diff --git a/Example/Tests/OMHSerializerTests.m b/Example/Tests/OMHSerializerTests.m index e6b7233..e63ba0a 100644 --- a/Example/Tests/OMHSerializerTests.m +++ b/Example/Tests/OMHSerializerTests.m @@ -1,7 +1,7 @@ -#import +#import #import #import -#import +#import #import "OMHSampleFactory.h" #import "OMHSchemaStore.h" #import "NSDate+RFC3339.h" @@ -100,7 +100,7 @@ }; NSMutableArray* tableRows = [NSMutableArray array]; [@[ - @[ @"HKObject type", @"HealthKitIO" ], + @[ @"HKObject type", @"Granola" ], @[ @"-------------", @":---------:" ], ] each:^(id row) { [tableRows push: row]; }]; [allTypesGrouped each:^(id groupName, id typesList){ @@ -126,9 +126,9 @@ id (^deserializedJsonForSample)(HKSample* sample) = ^(HKSample* sample){ - OMHSerializer* instance = [OMHSerializer forSample:sample error:nil]; - NSString* json = [instance jsonOrError:nil]; - NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding]; + OMHSerializer* instance = [OMHSerializer new]; + NSString* json = [instance jsonForSample:sample error:nil]; + NSData* data = [json dataUsingEncoding:NSUTF8StringEncoding]; return [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; @@ -155,22 +155,27 @@ }); }); - describe(@"+forSample:error:", ^{ - __block NSError* error = nil; + describe(@"-jsonForSample:error:", ^{ + __block NSError* error; __block HKSample* sample; __block OMHSerializer* instance; + __block NSString* json; + beforeEach(^{ + instance = [OMHSerializer new]; + }); it(@"without sample raises exception", ^{ expect(^{ - [OMHSerializer forSample:nil error:nil]; + [instance jsonForSample:nil error:nil]; }).to.raise(NSInternalInconsistencyException); }); context(@"with sample of unsupported type", ^{ beforeEach(^{ + error = nil; sample = [OMHSampleFactory typeIdentifier:unsupportedTypeIdentifier]; - instance = [OMHSerializer forSample:sample error:&error]; + json = [instance jsonForSample:sample error:&error]; }); it(@"returns nil", ^{ - expect(instance).to.beNil(); + expect(json).to.beNil(); }); it(@"populates error", ^{ expect(error).notTo.beNil(); @@ -181,10 +186,12 @@ [supportedTypeIdentifiers each:^(NSString* typeIdentifier){ context([NSString stringWithFormat: @"with sample of supported type %@", typeIdentifier], ^{ - it(@"and supported values returns instance", ^{ - sample = [OMHSampleFactory typeIdentifier:typeIdentifier]; - instance = [OMHSerializer forSample:sample error:&error]; - expect(instance).to.beKindOf([OMHSerializer class]); + it(@"and supported values returns json result without error", ^{ + NSError* error = nil; + HKSample* sample = [OMHSampleFactory typeIdentifier:typeIdentifier]; + json = [instance jsonForSample:sample error:&error]; + expect(json).notTo.beNil(); + expect(error).to.beNil(); }); }); }]; @@ -195,7 +202,7 @@ SharedExamplesBegin(AnySerializerForSupportedSample) sharedExamplesFor(@"AnySerializerForSupportedSample", ^(NSDictionary* data) { - describe(@"-jsonOrError:", ^{ + describe(@"-jsonForSample:error:", ^{ __block id object = nil; __block HKSample* sample = nil; __block id pathsToValues = nil; @@ -378,30 +385,22 @@ } }; }); - describe(@"+forSample:error:", ^{ - __block NSError* error = nil; - __block HKSample* sample; - __block OMHSerializer* instance; - context(@"if sample's value unsupported", ^{ - beforeEach(^{ - HKCategoryType* type = - [HKObjectType categoryTypeForIdentifier:identifier]; - sample = - [HKCategorySample categorySampleWithType:type - value:HKCategoryValueSleepAnalysisInBed - startDate:[NSDate date] - endDate:[NSDate date]]; - instance = [OMHSerializer forSample:sample error:&error]; - }); - it(@"returns nil", ^{ - OMHSerializer* instance = [OMHSerializer forSample:sample error:nil]; - expect(instance).to.beNil(); - }); - it(@"populates error", ^{ - expect(error).notTo.beNil(); - expect(error.code).to.equal(OMHErrorCodeUnsupportedValues); - expect(error.localizedDescription).to.contain(@"HKCategoryValueSleepAnalysis"); - }); + describe(@"-jsonForSample:error:", ^{ + it(@"returns nil and populates error if sample's value unsupported", ^{ + HKCategoryType* type = + [HKObjectType categoryTypeForIdentifier:identifier]; + HKSample* sample = + [HKCategorySample categorySampleWithType:type + value:HKCategoryValueSleepAnalysisInBed + startDate:[NSDate date] + endDate:[NSDate date]]; + OMHSerializer* instance = [OMHSerializer new]; + NSError* error; + NSString* json = [instance jsonForSample:sample error:&error]; + expect(json).to.beNil(); + expect(error).notTo.beNil(); + expect(error.code).to.equal(OMHErrorCodeUnsupportedValues); + expect(error.localizedDescription).to.contain(@"HKCategoryValueSleepAnalysis"); }); }); }); @@ -413,6 +412,7 @@ __block HKSample* systolicSample = nil; __block HKSample* sample = nil; __block NSDate* sampledAt = nil; + __block NSString* json = nil; beforeAll(^{ sampledAt = [NSDate date]; diastolicValue = [NSNumber numberWithDouble:60]; @@ -428,7 +428,7 @@ @"end": sampledAt, @"value": systolicValue }]; }); - describe(@"+forSample:error:", ^{ + describe(@"-jsonForSample:error:", ^{ __block NSError* error = nil; __block OMHSerializer* instance = nil; context(@"with sample lacking either a systolic or diastolic sample", ^{ @@ -439,10 +439,11 @@ attrs:@{ @"start": sampledAt, @"end": sampledAt, @"objects": objects }]; - instance = [OMHSerializer forSample:sample error:&error]; + instance = [OMHSerializer new]; + json = [instance jsonForSample:sample error:&error]; }); it(@"returns nil", ^{ - expect(instance).to.beNil(); + expect(json).to.beNil(); }); it(@"populates error", ^{ expect(error).notTo.beNil(); diff --git a/Granola.podspec b/Granola.podspec new file mode 100644 index 0000000..1dded18 --- /dev/null +++ b/Granola.podspec @@ -0,0 +1,18 @@ +Pod::Spec.new do |s| + s.name = "Granola" + s.version = "0.1.0" + s.summary = "A healthful serializer for your HealthKit data." + s.homepage = "https://github.com/openmhealth/Granola" + s.license = { :type => 'Apache 2.0', + :file => 'LICENSE' } + s.authors = { "Brent Hargrave" => "brent@brent.is" } + s.source = { :git => "https://github.com/openmhealth/Granola.git", + :tag => s.version.to_s } + s.social_media_url = 'https://twitter.com/openmhealth' + s.platform = :ios, '7.0' + s.requires_arc = true + s.source_files = 'Pod/Classes/**/*' + s.frameworks = 'HealthKit' + s.dependency 'ObjectiveSugar', '~> 1.1' +end + diff --git a/HealthKitIO.podspec b/HealthKitIO.podspec deleted file mode 100644 index 7819047..0000000 --- a/HealthKitIO.podspec +++ /dev/null @@ -1,39 +0,0 @@ -# -# Be sure to run `pod lib lint HealthKitIO.podspec' to ensure this is a -# valid spec and remove all comments before submitting the spec. -# -# Any lines starting with a # are optional, but encouraged -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html -# - -Pod::Spec.new do |s| - s.name = "HealthKitIO" - s.version = "0.1.0" - s.summary = "A short description of HealthKitIO." - s.description = <<-DESC - An optional longer description of HealthKitIO - - * Markdown format. - * Don't worry about the indent, we strip it! - DESC - s.homepage = "https://github.com//HealthKitIO" - # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" - s.license = 'MIT' - s.author = { "Brent Hargrave" => "brent@brent.is" } - s.source = { :git => "https://github.com/openmhealth/HealthKitIO.git", :tag => s.version.to_s } - # s.social_media_url = 'https://twitter.com/' - - s.platform = :ios, '7.0' - s.requires_arc = true - - s.source_files = 'Pod/Classes/**/*' - s.resource_bundles = { - 'HealthKitIO' => ['Pod/Assets/*.png'] - } - - # s.public_header_files = 'Pod/Classes/**/*.h' - # s.frameworks = 'UIKit', 'MapKit' - s.dependency 'ObjectiveSugar', '~> 1.1' -end - diff --git a/LICENSE b/LICENSE index 6962761..5c304d1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,19 +1,201 @@ -Copyright (c) 2015 Brent Hargrave - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Pod/Classes/NSDate+RFC3339.h b/Pod/Classes/NSDate+RFC3339.h index 05cfff3..450d371 100644 --- a/Pod/Classes/NSDate+RFC3339.h +++ b/Pod/Classes/NSDate+RFC3339.h @@ -4,4 +4,7 @@ - (NSString *)RFC3339String; ++ (NSDate*)fromRFC3339String:(NSString*)dateString; + @end + diff --git a/Pod/Classes/NSDate+RFC3339.m b/Pod/Classes/NSDate+RFC3339.m index 458e57f..a920ff6 100644 --- a/Pod/Classes/NSDate+RFC3339.m +++ b/Pod/Classes/NSDate+RFC3339.m @@ -2,12 +2,25 @@ @implementation NSDate (RFC3339) ++ (NSDateFormatter*)RFC3339Formatter { + static NSDateFormatter* formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + NSLocale* locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + [formatter setLocale:locale]; + [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z"]; + }); + return formatter; +} + - (NSString *)RFC3339String { - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; - [dateFormatter setLocale:locale]; - [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z"]; - return [dateFormatter stringFromDate:self]; + return [[[self class] RFC3339Formatter] stringFromDate:self]; +} + ++ (NSDate*)fromRFC3339String:(NSString*)dateString { + return [[self RFC3339Formatter] dateFromString:dateString]; } @end + diff --git a/Pod/Classes/OMHError.m b/Pod/Classes/OMHError.m index fe39058..3be26d4 100644 --- a/Pod/Classes/OMHError.m +++ b/Pod/Classes/OMHError.m @@ -1,4 +1,4 @@ #import "OMHError.h" -NSString *const OMHErrorDomain = @"org.openmhealth.HealthKitIO"; +NSString *const OMHErrorDomain = @"org.openmhealth.Granola"; diff --git a/Pod/Classes/OMHSerializer.h b/Pod/Classes/OMHSerializer.h index 0bde7a6..6874aed 100644 --- a/Pod/Classes/OMHSerializer.h +++ b/Pod/Classes/OMHSerializer.h @@ -6,10 +6,7 @@ + (NSArray*)supportedTypeIdentifiers; -+ (id)forSample:(HKSample*)sample error:(NSError**)error; -- (id)initWithSample:(HKSample*)sample; - -- (NSString*)jsonOrError:(NSError**)serializationError; +- (NSString*)jsonForSample:(HKSample*)sample error:(NSError**)error; @end diff --git a/Pod/Classes/OMHSerializer.m b/Pod/Classes/OMHSerializer.m index 16f71d4..b8f03d9 100644 --- a/Pod/Classes/OMHSerializer.m +++ b/Pod/Classes/OMHSerializer.m @@ -37,18 +37,22 @@ + (BOOL)canSerialize:(HKSample*)sample error:(NSError**)error { @throw [self unimplementedException]; } -+ (id)forSample:(HKSample*)sample error:(NSError**)error { +- (id)initWithSample:(HKSample*)sample { + self = [super init]; + if (self) { + _sample = sample; + } else { + return nil; + } + return self; +} + +- (NSString*)jsonForSample:(HKSample*)sample error:(NSError**)error { NSParameterAssert(sample); - NSArray* supportedTypeIdentifiers = [self supportedTypeIdentifiers]; + // first, verify we support the sample type + NSArray* supportedTypeIdentifiers = [[self class] supportedTypeIdentifiers]; NSString* sampleTypeIdentifier = sample.sampleType.identifier; - if ([supportedTypeIdentifiers includes:sampleTypeIdentifier]) { - NSString* serializerClassName = - [self typeIdentifiersToClasses][sampleTypeIdentifier]; - Class serializerClass = NSClassFromString(serializerClassName); - if ([serializerClass canSerialize:sample error:error]) { - return [[serializerClass alloc] initWithSample:sample]; - } - } else { + if (![supportedTypeIdentifiers includes:sampleTypeIdentifier]) { if (error) { NSString* errorMessage = [NSString stringWithFormat: @"Unsupported HKSample type: %@", @@ -58,34 +62,28 @@ + (id)forSample:(HKSample*)sample error:(NSError**)error { code: OMHErrorCodeUnsupportedType userInfo: userInfo]; } + return nil; } - return nil; -} - -- (id)initWithSample:(HKSample*)sample { - self = [super init]; - if (self) { - _sample = sample; - } else { + // if we support it, select appropriate subclass for sample + NSString* serializerClassName = + [[self class] typeIdentifiersToClasses][sampleTypeIdentifier]; + Class serializerClass = NSClassFromString(serializerClassName); + // subclass verifies it supports sample's values + if (![serializerClass canSerialize:sample error:error]) { return nil; } - return self; -} - -- (NSString*)jsonOrError:(NSError**)serializationError { - NSData *jsonData = - [NSJSONSerialization dataWithJSONObject:[self data] + // instantiate a serializer + OMHSerializer* serializer = [[serializerClass alloc] initWithSample:sample]; + NSData* jsonData = + [NSJSONSerialization dataWithJSONObject:[serializer data] options:NSJSONWritingPrettyPrinted - error:serializationError]; - if (jsonData) { - NSString *jsonString = - [[NSString alloc] initWithData:jsonData - encoding:NSUTF8StringEncoding]; - return jsonString; - } else { - // serialization error populated, return nil - return nil; + error:error]; + if (!jsonData) { + return nil; // return early if JSON serialization failed } + NSString* jsonString = [[NSString alloc] initWithData:jsonData + encoding:NSUTF8StringEncoding]; + return jsonString; } #pragma mark - Private diff --git a/README.md b/README.md index ddf48b6..156b2d2 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,17 @@ -# HealthKitIO - -(TODO: perhaps create a logo? Examples: -[AFNetworking](https://github.com/AFNetworking/AFNetworking), -[CocoaLumberjack](https://github.com/CocoaLumberjack/CocoaLumberjack), -[Alamofire](https://github.com/Alamofire/Alamofire), -[Spring](https://github.com/MengTo/Spring), -[Quick](https://github.com/Quick/Quick)) - -(TODO: continuous integration badges, like...) -[![CI Status](http://img.shields.io/travis/openmhealth/HealthKitIO.svg?style=flat)](https://travis-ci.org/openmhealth/HealthKitIO) -[![Version](https://img.shields.io/cocoapods/v/HealthKitIO.svg?style=flat)](http://cocoapods.org/pods/HealthKitIO) -[![License](https://img.shields.io/cocoapods/l/HealthKitIO.svg?style=flat)](http://cocoapods.org/pods/HealthKitIO) -[![Platform](https://img.shields.io/cocoapods/p/HealthKitIO.svg?style=flat)](http://cocoapods.org/pods/HealthKitIO) +# Granola +_*A healthful serializer for your HealthKit data.*_ ## Overview -So you want to store your app's [HealthKit](https://developer.apple.com/healthkit/) data somewhere *outside* of HealthKit, perhaps a remote server for analysis or backup? Use HealthKitIO to serialize your data. +So you want to store your app's [HealthKit](https://developer.apple.com/healthkit/) +data somewhere *outside* of HealthKit, perhaps a remote server for analysis or +backup? Use Granola to serialize your data. -HealthKitIO spares you the effort of mapping HealthKit's API to JSON yourself, -and emits JSON that validates against [schemas developed by Open mHealth](http://www.openmhealth.org/developers/schemas/) to ensure the data is intuitive and clinically meaningful. +Granola spares you the effort of mapping HealthKit's API to JSON yourself, +and emits JSON that validates against +[schemas developed by Open mHealth](http://www.openmhealth.org/developers/schemas/) +to ensure the data is intuitive and clinically meaningful. *** @@ -28,11 +20,10 @@ and emits JSON that validates against [schemas developed by Open mHealth](http:/ ### CocoaPods -HealthKitIO is available through [CocoaPods](http://cocoapods.org). To install -it, simply add the following line to your `Podfile`: +Granola is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your `Podfile`: ```ruby -pod "HealthKitIO" +pod "Granola" ``` *** @@ -41,12 +32,17 @@ pod "HealthKitIO" ### Quick start -First, be sure to study Apple's [HealthKit Framework Reference](https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Framework), which includes code samples illustrating how to ask your app's user for permission to access their HealthKit data, and how to query that data after you've gained permission. +First, be sure to study Apple's +[HealthKit Framework Reference](https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Framework), +which includes code samples illustrating how to ask your app's user for +permission to access their HealthKit data, and how to query that data after +you've gained permission. -Now, let's say you want to see what a "steps" sample data point looks like serialized to JSON. +Now, let's say you want to see what a "steps" sample data point looks like +serialized to JSON. ```objective-c -// HealthKitIO includes OMHSerializer for serializing HealthKit data +// Granola includes OMHSerializer for serializing HealthKit data #import "OMHSerializer.h" // (initialize your HKHealthStore instance, request permissions with it) @@ -66,9 +62,9 @@ HKSampleQuery* query = if (!results) abort(); // pick a sample to serialize HKQuantitySample *sample = [results first]; - // create a serializer with the sample, skip error-handling for example - OMHSerializer *serializer = [OMHSerializer forHKSample:sample error:nil]; - NSString* jsonString = [serializer jsonOrError:nil]; + // create and use a serializer instance + OMHSerializer *serializer = [OMHSerializer new]; + NSString* jsonString = [serializer jsonForSample:sample error:nil]; NSLog(@"sample json: %@", jsonString); }]; // run the query with your authorized HKHealthStore instance @@ -79,33 +75,47 @@ Upon running your code, the console would render the data sample as Open mHealth ```json { - "effective-time-frame" : { - "end-time" : "2014-09-17T19:44:32-04:00", - "start-time" : "2014-09-17T19:44:27-04:00" + "body" : { + "step_count" : 45, + "effective_time_frame" : { + "time_interval" : { + "start_date_time" : "2015-05-12T18:58:06.969Z", + "end_date_time" : "2015-05-12T18:58:32.524Z" + } + } }, - "step_count" : 14 + "header" : { + "id" : "4A00E553-B01D-4757-ADD0-A4283BABAC6F", + "creation_date_time" : "2015-05-12T18:58:06.969Z", + "schema_id" : { + "namespace" : "omh", + "name" : "step-count", + "version" : "1.0" + } + } } ``` ### HKObjectType support -The serializer doesn't yet support all of HealthKit's data types. The list of supported types is available through a class method: +The serializer doesn't yet support all of HealthKit's data types. The list of +supported types is available through a class method: ```objective-c [OMHSerializer supportedTypeIdentifiers] //=> [HKQuantityTypeIdentifierStepCount, ...] ``` -Attempting to init a serializer with an HKObject of unsupported type or values -returns `nil` and populates the provided error. +Attempting to serialize an HKObject of unsupported type or values returns `nil` +and populates the provided error. ```objective-c HKQuantitySample *sampleOfUnsupportedType = [results first]; // create a serializer with the sample NSError* error = nil; -OMHSerializer *serializer = - [[OMHSerializer alloc] initWithHKSample:sampleOfUnsupportedType - error:&error]; +OMHSerializer *serializer = [OMHSerializer new]; +NSString* jsonString = [serializer jsonForSample:sampleOfUnsupportedType + error:&error]; if (serializer == nil) { // handle failure NSLog(@"%@", error.localizedDescription]; @@ -114,18 +124,20 @@ if (serializer == nil) { } ``` -Support for all possible HKObjectType identifiers, pulled from -the [HealthKit Constant Reference](https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Constants/index.html#//apple_ref/doc/constant_group/Body_Measurements), -is summarized [here](../doc/hkobject_type_coverage.md). Note that the majority +Support for all possible HKObjectType identifiers, pulled from the +[HealthKit Constant Reference](https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Constants), +is summarized [here](Docs/hkobject_type_coverage.md). Note that the majority of these identifiers are not yet in use by most applications. -[Contact us](#contact) to request support for a particular type or +[Contact us](##contact) to request support for a particular type or [contribute](#contributing) support with a pull request. ## Contact -Follow HealthKitIO on Twitter (@HealthKitIO) +Have a question? Please [open an issue](https://github.com/openmhealth/Granola/issues/new)! + +Also, feel free to tweet at Open mHealth ([@openmhealth](http://twitter.com/openmhealth)). ## Contributing @@ -139,5 +151,10 @@ Follow HealthKitIO on Twitter (@HealthKitIO) ## License -HealthKitIO is available under the MIT license. See the LICENSE file for more info. +Granola is available under the Apache 2 license. See the [LICENSE](/LICENSE) file for more info. + + +## Authors + +Brent Hargrave ([@brenthargrave](http://twitter.com/brenthargrave))