Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b1153da04 |
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyTrackingDomains</key>
|
||||
<array/>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypeAudioData</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<true/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypePhotosorVideos</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<true/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypeSensitiveInfo</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypeHealth</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<true/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypePreciseLocation</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<true/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -260,6 +260,28 @@ types of steps supported by the *ResearchKit framework* in the first tab, and di
|
||||
results of the last completed task in the second tab. The third tab shows some examples from the *Charts module*.
|
||||
|
||||
|
||||
App Store Submissions
|
||||
-----------------------------
|
||||
|
||||
For apps that don’t use ResearchKit’s HealthKit features:
|
||||
If you are looking to submit your app with ResearchKit to the App Store, you can compile out unnecessary references to HealthKit in your app by editing the following project file:
|
||||
`ResearchKit/Configuration/ResearchKit/ResearchKit-Shared.xcconfig`
|
||||
And changing
|
||||
`ORK_FEATURE_HEALTHKIT_AUTHORIZATION=1`
|
||||
To
|
||||
`ORK_FEATURE_HEALTHKIT_AUTHORIZATION=0`
|
||||
|
||||
With this change, the embedded ResearchKit framework in your app will not contain any HealthKit related functionality or any references to HealthKit API that might trigger AppStore review to require HealthKit entries in your app’s Info.plist.
|
||||
|
||||
Similarly, if you would like to compile out references to CoreLocation. In the same `ResearchKit-Shared.xcconfig`
|
||||
And changing
|
||||
`ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=1`
|
||||
To
|
||||
`ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=0`
|
||||
|
||||
Also please ensure that your `info.plist` does not have any HealthKit privacy messages
|
||||
|
||||
Similarly, if you would like to use the ResearchKit’s HealthKit features. Make sure to enable the HealthKit Entitlement
|
||||
|
||||
License<a name="license"></a>
|
||||
=======
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'ResearchKit'
|
||||
s.version = '2.2.15'
|
||||
s.version = '2.2.16'
|
||||
s.summary = 'ResearchKit is an open source software framework that makes it easy to create apps for medical research or for other research projects.'
|
||||
s.homepage = 'https://www.github.com/ResearchKit/ResearchKit'
|
||||
s.documentation_url = 'http://researchkit.github.io/docs/'
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
00B1F7852241503900D022FE /* Speech.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00B1F7842241503900D022FE /* Speech.framework */; };
|
||||
00B1F7852241503900D022FE /* Speech.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00B1F7842241503900D022FE /* Speech.framework */; settings = {ATTRIBUTES = (Required, ); }; };
|
||||
00C2668A2302244300337E0B /* ORKCustomStepViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 00C266882302244300337E0B /* ORKCustomStepViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00C2668B2302244300337E0B /* ORKCustomStepViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 00C266892302244300337E0B /* ORKCustomStepViewController.m */; };
|
||||
00C2668E23022CD400337E0B /* ORKCustomStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 00C2668C23022CD400337E0B /* ORKCustomStep.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -41,6 +41,9 @@
|
||||
03BD9EA4253E62A0008ADBE1 /* ORKBundleAsset.m in Sources */ = {isa = PBXBuildFile; fileRef = 03BD9EA2253E62A0008ADBE1 /* ORKBundleAsset.m */; };
|
||||
03EDD58024CA6B1D006245E9 /* ORKNotificationPermissionType.h in Headers */ = {isa = PBXBuildFile; fileRef = 03EDD57E24CA6B1D006245E9 /* ORKNotificationPermissionType.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
03EDD58124CA6B1D006245E9 /* ORKNotificationPermissionType.m in Sources */ = {isa = PBXBuildFile; fileRef = 03EDD57F24CA6B1D006245E9 /* ORKNotificationPermissionType.m */; };
|
||||
0B0EF9C92B8FB87600E2A97B /* ResearchKitTests-Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 0B0EF9C72B8FB87600E2A97B /* ResearchKitTests-Shared.xcconfig */; };
|
||||
0B0EF9CA2B8FB87600E2A97B /* ResearchKitTests-Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 0B0EF9C82B8FB87600E2A97B /* ResearchKitTests-Debug.xcconfig */; };
|
||||
0B4D0F982BC87AB100DCB8B2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 0B4D0F972BC87AB100DCB8B2 /* PrivacyInfo.xcprivacy */; };
|
||||
0B59A6BF28C1738D005035B4 /* ORKPickerTestDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B59A6BE28C1738D005035B4 /* ORKPickerTestDelegate.m */; };
|
||||
0B6CD14329119C7F004BC4A0 /* ORKNormalizedReactionTimeStimulusView.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAF9797291088EE00EF138A /* ORKNormalizedReactionTimeStimulusView.h */; };
|
||||
0B6CD14429119CBA004BC4A0 /* ORKNormalizedReactionTimeContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAF9798291088EE00EF138A /* ORKNormalizedReactionTimeContentView.h */; };
|
||||
@@ -199,6 +202,9 @@
|
||||
2E80C1AA1FA2AA8D00399A0C /* ORKStreamingAudioRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E80C1A91FA2AA8D00399A0C /* ORKStreamingAudioRecorder.m */; };
|
||||
2EBFE11D1AE1B32D00CB8254 /* ORKUIViewAccessibilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EBFE11C1AE1B32D00CB8254 /* ORKUIViewAccessibilityTests.m */; };
|
||||
2EBFE1201AE1B74100CB8254 /* ORKVoiceEngineTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EBFE11F1AE1B74100CB8254 /* ORKVoiceEngineTests.m */; };
|
||||
3C13A8A52BACDCD8006CB592 /* ORKTouchAbilityTouchTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 511B8AAC293A767C00049947 /* ORKTouchAbilityTouchTracker.h */; };
|
||||
3C7AEDCC29A72F83009EED4A /* CLLocationManager+ResearchKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C7AEDCA29A72F83009EED4A /* CLLocationManager+ResearchKit.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
3C7AEDCD29A72F83009EED4A /* CLLocationManager+ResearchKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C7AEDCB29A72F83009EED4A /* CLLocationManager+ResearchKit.m */; };
|
||||
51198769245CA50D004FC2C7 /* ORKUSDZModelManagerScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 51198767245CA50D004FC2C7 /* ORKUSDZModelManagerScene.h */; };
|
||||
5119876A245CA50D004FC2C7 /* ORKUSDZModelManagerScene.m in Sources */ = {isa = PBXBuildFile; fileRef = 51198768245CA50D004FC2C7 /* ORKUSDZModelManagerScene.m */; };
|
||||
5119879B245FC33C004FC2C7 /* ORK3DModelManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 51198799245FC33C004FC2C7 /* ORK3DModelManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -225,7 +231,6 @@
|
||||
511B8AA8293A764900049947 /* ORKTouchAbilityTrial.m in Sources */ = {isa = PBXBuildFile; fileRef = 511B8AA6293A764900049947 /* ORKTouchAbilityTrial.m */; };
|
||||
511B8AAA293A766300049947 /* ORKTouchAbilityTrial_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 511B8AA9293A766300049947 /* ORKTouchAbilityTrial_Internal.h */; };
|
||||
511B8AAD293A767C00049947 /* ORKTouchAbilityTouchTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 511B8AAB293A767C00049947 /* ORKTouchAbilityTouchTracker.m */; };
|
||||
511B8AAE293A767C00049947 /* ORKTouchAbilityTouchTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 511B8AAC293A767C00049947 /* ORKTouchAbilityTouchTracker.h */; };
|
||||
511B8AB1293A76A100049947 /* ORKTouchAbilityTapStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 511B8AAF293A76A100049947 /* ORKTouchAbilityTapStep.m */; };
|
||||
511B8AB2293A76A100049947 /* ORKTouchAbilityTapStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 511B8AB0293A76A100049947 /* ORKTouchAbilityTapStep.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
511B8AB5293A76B200049947 /* ORKTouchAbilityTapStepViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 511B8AB3293A76B200049947 /* ORKTouchAbilityTapStepViewController.m */; };
|
||||
@@ -760,7 +765,6 @@
|
||||
B1A860F61A9693C400EA57B7 /* consent_06@3x.m4v in Resources */ = {isa = PBXBuildFile; fileRef = B1A860E81A9693C400EA57B7 /* consent_06@3x.m4v */; };
|
||||
B1A860F71A9693C400EA57B7 /* consent_07@3x.m4v in Resources */ = {isa = PBXBuildFile; fileRef = B1A860E91A9693C400EA57B7 /* consent_07@3x.m4v */; };
|
||||
B1C0F4E41A9BA65F0022C153 /* ResearchKit.strings in Resources */ = {isa = PBXBuildFile; fileRef = B1C0F4E11A9BA65F0022C153 /* ResearchKit.strings */; };
|
||||
B1C7955E1A9FBF04007279BA /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1C7955D1A9FBF04007279BA /* HealthKit.framework */; settings = {ATTRIBUTES = (Required, ); }; };
|
||||
B8760F2B1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.h in Headers */ = {isa = PBXBuildFile; fileRef = B8760F291AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.h */; };
|
||||
B8760F2C1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = B8760F2A1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.m */; };
|
||||
BA0AA6941EAEC0B600671ACE /* ORKStroopContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = BA0AA68E1EAEC0B600671ACE /* ORKStroopContentView.h */; };
|
||||
@@ -1046,6 +1050,9 @@
|
||||
03EDD57E24CA6B1D006245E9 /* ORKNotificationPermissionType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORKNotificationPermissionType.h; sourceTree = "<group>"; };
|
||||
03EDD57F24CA6B1D006245E9 /* ORKNotificationPermissionType.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORKNotificationPermissionType.m; sourceTree = "<group>"; };
|
||||
05F3765923C797930068E166 /* ResearchKit.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = ResearchKit.xctestplan; sourceTree = "<group>"; };
|
||||
0B0EF9C72B8FB87600E2A97B /* ResearchKitTests-Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "ResearchKitTests-Shared.xcconfig"; sourceTree = "<group>"; };
|
||||
0B0EF9C82B8FB87600E2A97B /* ResearchKitTests-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "ResearchKitTests-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||
0B4D0F972BC87AB100DCB8B2 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
0B59A6BD28C1738D005035B4 /* ORKPickerTestDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORKPickerTestDelegate.h; sourceTree = "<group>"; };
|
||||
0B59A6BE28C1738D005035B4 /* ORKPickerTestDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORKPickerTestDelegate.m; sourceTree = "<group>"; };
|
||||
0B7D32E92AE6F8040071C576 /* ORKQuestionStepViewController+TestingSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ORKQuestionStepViewController+TestingSupport.h"; sourceTree = "<group>"; };
|
||||
@@ -1208,6 +1215,8 @@
|
||||
2EBFE11C1AE1B32D00CB8254 /* ORKUIViewAccessibilityTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKUIViewAccessibilityTests.m; sourceTree = "<group>"; };
|
||||
2EBFE11E1AE1B68800CB8254 /* ORKVoiceEngine_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORKVoiceEngine_Internal.h; sourceTree = "<group>"; };
|
||||
2EBFE11F1AE1B74100CB8254 /* ORKVoiceEngineTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKVoiceEngineTests.m; sourceTree = "<group>"; };
|
||||
3C7AEDCA29A72F83009EED4A /* CLLocationManager+ResearchKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CLLocationManager+ResearchKit.h"; sourceTree = "<group>"; };
|
||||
3C7AEDCB29A72F83009EED4A /* CLLocationManager+ResearchKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CLLocationManager+ResearchKit.m"; sourceTree = "<group>"; };
|
||||
51198767245CA50D004FC2C7 /* ORKUSDZModelManagerScene.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORKUSDZModelManagerScene.h; sourceTree = "<group>"; };
|
||||
51198768245CA50D004FC2C7 /* ORKUSDZModelManagerScene.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORKUSDZModelManagerScene.m; sourceTree = "<group>"; };
|
||||
51198799245FC33C004FC2C7 /* ORK3DModelManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORK3DModelManager.h; sourceTree = "<group>"; };
|
||||
@@ -1819,7 +1828,6 @@
|
||||
B1B34A061AA10EE4005FAD66 /* ar */ = {isa = PBXFileReference; explicitFileType = text.plist.strings; name = ar; path = ar.lproj/ResearchKit.strings; sourceTree = "<group>"; };
|
||||
B1C0F4E21A9BA65F0022C153 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/ResearchKit.strings; sourceTree = "<group>"; };
|
||||
B1C1DE4F196F541F00F75544 /* ResearchKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResearchKit.h; sourceTree = "<group>"; };
|
||||
B1C7955D1A9FBF04007279BA /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
|
||||
B8760F291AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKScaleRangeDescriptionLabel.h; sourceTree = "<group>"; };
|
||||
B8760F2A1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKScaleRangeDescriptionLabel.m; sourceTree = "<group>"; };
|
||||
BA0AA68E1EAEC0B600671ACE /* ORKStroopContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKStroopContentView.h; sourceTree = "<group>"; };
|
||||
@@ -2079,7 +2087,6 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
00B1F7852241503900D022FE /* Speech.framework in Frameworks */,
|
||||
B1C7955E1A9FBF04007279BA /* HealthKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2097,6 +2104,16 @@
|
||||
name = "Custom Step";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0B0EF9C62B8FB87600E2A97B /* ResearchKitTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0B0EF9C72B8FB87600E2A97B /* ResearchKitTests-Shared.xcconfig */,
|
||||
0B0EF9C82B8FB87600E2A97B /* ResearchKitTests-Debug.xcconfig */,
|
||||
);
|
||||
name = ResearchKitTests;
|
||||
path = ResearchKit/Configuration/ResearchKitTests;
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
0BAF947D2910887D00EF138A /* Shake */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2375,6 +2392,8 @@
|
||||
5D04885525F19A7A0006C68B /* ORKDevice.h */,
|
||||
5D04885B25F1B3AB0006C68B /* ORKDevice_Private.h */,
|
||||
5D04885625F19A7A0006C68B /* ORKDevice.m */,
|
||||
3C7AEDCA29A72F83009EED4A /* CLLocationManager+ResearchKit.h */,
|
||||
3C7AEDCB29A72F83009EED4A /* CLLocationManager+ResearchKit.m */,
|
||||
);
|
||||
name = Utilities;
|
||||
sourceTree = "<group>";
|
||||
@@ -2493,6 +2512,7 @@
|
||||
3FFF18341829DB1D00167070 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0B4D0F972BC87AB100DCB8B2 /* PrivacyInfo.xcprivacy */,
|
||||
05F3765923C797930068E166 /* ResearchKit.xctestplan */,
|
||||
168EEAAE230B6F9E003FD2FA /* scripts */,
|
||||
B11DF3B21AA109C8009E76D2 /* docs */,
|
||||
@@ -2516,7 +2536,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00B1F7842241503900D022FE /* Speech.framework */,
|
||||
B1C7955D1A9FBF04007279BA /* HealthKit.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -2872,21 +2891,6 @@
|
||||
name = "HealthKit Permission Type";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
51EAFC10289B116300CFA3EB /* Configuration */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
51EAFC11289B117500CFA3EB /* ResearchKit */,
|
||||
);
|
||||
path = Configuration;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
51EAFC11289B117500CFA3EB /* ResearchKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = ResearchKit;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5D000EC02620F27100E5442A /* Configuration */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2898,6 +2902,7 @@
|
||||
5D000EC12620F27100E5442A /* ResearchKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0B0EF9C62B8FB87600E2A97B /* ResearchKitTests */,
|
||||
5D000EC22620F27100E5442A /* ResearchKit-Debug.xcconfig */,
|
||||
5D000EC42620F27100E5442A /* ResearchKit-Shared.xcconfig */,
|
||||
511A78992950D7030011D85D /* ResearchKit-Release.xcconfig */,
|
||||
@@ -3042,7 +3047,6 @@
|
||||
B1C1DE4F196F541F00F75544 /* ResearchKit.h */,
|
||||
BC94EF2F1E962F7400143081 /* ORKDeprecated.h */,
|
||||
BC94EF301E962F7400143081 /* ORKDeprecated.m */,
|
||||
51EAFC10289B116300CFA3EB /* Configuration */,
|
||||
86C40B511A8D7C5B00081FAC /* Common */,
|
||||
86C40AF91A8D7C5B00081FAC /* Active Tasks */,
|
||||
259E76FB1AFFAEAC0070F786 /* Charts */,
|
||||
@@ -4312,6 +4316,7 @@
|
||||
BCB6E65B1B7D534C000D5B34 /* ORKDiscreteGraphChartView.h in Headers */,
|
||||
86C40D8E1A8D7C5C00081FAC /* ORKStep.h in Headers */,
|
||||
511987C72463316E004FC2C7 /* ORKRequestPermissionsStepViewController.h in Headers */,
|
||||
3C7AEDCC29A72F83009EED4A /* CLLocationManager+ResearchKit.h in Headers */,
|
||||
618DA04E1A93D0D600E63AA8 /* ORKAccessibility.h in Headers */,
|
||||
BA6E1EB6209E9A3F00DA9D55 /* ORKPDFViewerStepView_Internal.h in Headers */,
|
||||
BAC6F1A922AF535100E31C22 /* ORKTaskReviewViewController.h in Headers */,
|
||||
@@ -4603,6 +4608,7 @@
|
||||
511B8AB6293A76B200049947 /* ORKTouchAbilityTapStepViewController.h in Headers */,
|
||||
D458520A1AF6CCFA00A2DE13 /* ORKImageCaptureCameraPreviewView.h in Headers */,
|
||||
D44239791AF17F5100559D96 /* ORKImageCaptureStep.h in Headers */,
|
||||
3C13A8A52BACDCD8006CB592 /* ORKTouchAbilityTouchTracker.h in Headers */,
|
||||
511B8AF9293A78BB00049947 /* ORKTouchAbilityScrollStep.h in Headers */,
|
||||
86C40CB21A8D7C5C00081FAC /* ORKRecorder_Private.h in Headers */,
|
||||
BCD192E71B81243900FCC08A /* ORKPieChartLegendView.h in Headers */,
|
||||
@@ -4895,6 +4901,8 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0B0EF9CA2B8FB87600E2A97B /* ResearchKitTests-Debug.xcconfig in Resources */,
|
||||
0B0EF9C92B8FB87600E2A97B /* ResearchKitTests-Shared.xcconfig in Resources */,
|
||||
22ED1848285290250052406B /* ORKAudiometryTestData.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -4921,6 +4929,7 @@
|
||||
2246E5152749350300261D5A /* frequency_dBSPL_AIRPODSV3.plist in Resources */,
|
||||
B1A860F31A9693C400EA57B7 /* consent_03@3x.m4v in Resources */,
|
||||
B1A860F11A9693C400EA57B7 /* consent_01@3x.m4v in Resources */,
|
||||
0B4D0F982BC87AB100DCB8B2 /* PrivacyInfo.xcprivacy in Resources */,
|
||||
E26E32D722E75FBF004F42EC /* Window.wav in Resources */,
|
||||
62DF9F4728CA87DE00D13018 /* frequency_dBSPL_AIRPODSPROV2.plist in Resources */,
|
||||
B1A860F71A9693C400EA57B7 /* consent_07@3x.m4v in Resources */,
|
||||
@@ -5026,7 +5035,6 @@
|
||||
714151D0225C4A23002CA33B /* ORKPasscodeViewControllerTests.swift in Sources */,
|
||||
0324C1D825439E1800BBE77B /* ORKVideoInstructionStepViewControllerTests.swift in Sources */,
|
||||
14E79040226A5F72009D8083 /* ORKStepViewControllerHelpers.swift in Sources */,
|
||||
0BC803602B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.m in Sources */,
|
||||
86D348021AC161B0006DB02B /* ORKRecorderTests.m in Sources */,
|
||||
1490DCFC224D4867003FEEDA /* ORKEnvironmentSPLMeterResultTests.swift in Sources */,
|
||||
7141EA2222EFBC0C00650145 /* ORKLoggingTests.m in Sources */,
|
||||
@@ -5203,6 +5211,7 @@
|
||||
BA8C067922EEB84B00ACDE6B /* ORKPlaybackButton.m in Sources */,
|
||||
86C40C401A8D7C5C00081FAC /* ORKSpatialSpanMemoryContentView.m in Sources */,
|
||||
511B8B12293A796600049947 /* ORKTouchAbilityPinchContentView.m in Sources */,
|
||||
3C7AEDCD29A72F83009EED4A /* CLLocationManager+ResearchKit.m in Sources */,
|
||||
BAC6F1AA22AF535100E31C22 /* ORKTaskReviewViewController.m in Sources */,
|
||||
BCB6E6671B7D535F000D5B34 /* ORKXAxisView.m in Sources */,
|
||||
00C2668B2302244300337E0B /* ORKCustomStepViewController.m in Sources */,
|
||||
@@ -5561,6 +5570,7 @@
|
||||
};
|
||||
86CC8EA41AC09332001CCD89 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 0B0EF9C82B8FB87600E2A97B /* ResearchKitTests-Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ADDRESS_SANITIZER_CONTAINER_OVERFLOW = YES;
|
||||
@@ -5569,6 +5579,10 @@
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"$(ORK_GCC_PREPROCESSOR_DEFINITIONS)",
|
||||
);
|
||||
INFOPLIST_FILE = ResearchKitTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#import "ORKDefines.h"
|
||||
|
||||
@import HealthKit;
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@@ -60,3 +62,5 @@ typedef NS_OPTIONS(NSInteger, ORKSampleJSONOptions) {
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,7 +45,7 @@ static NSString *const HKUnitKey = @"unit";
|
||||
static NSString *const HKCorrelatedObjectsKey = @"objects";
|
||||
// static NSString *const HKSourceIdentifierKey = @"sourceBundleIdentifier";
|
||||
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
@implementation HKSample (ORKJSONDictionary)
|
||||
|
||||
- (NSMutableDictionary *)ork_JSONMutableDictionaryWithOptions:(ORKSampleJSONOptions)options unit:(HKUnit *)unit {
|
||||
@@ -167,3 +167,4 @@ static NSString *const HKCorrelatedObjectsKey = @"objects";
|
||||
}
|
||||
|
||||
@end
|
||||
#endif // ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
|
||||
@import UIKit;
|
||||
@import HealthKit;
|
||||
#import <ResearchKit/ORKStep.h>
|
||||
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@
|
||||
(self.shouldUseNextAsSkipButton == castObject.shouldUseNextAsSkipButton));
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (NSSet<HKObjectType *> *)requestedHealthKitTypesForReading {
|
||||
NSMutableSet<HKObjectType *> *set = [NSMutableSet set];
|
||||
for (ORKRecorderConfiguration *config in self.recorderConfigurations) {
|
||||
@@ -175,6 +176,7 @@
|
||||
}
|
||||
return set;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (ORKPermissionMask)requestedPermissions {
|
||||
ORKPermissionMask mask = [super requestedPermissions];
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#import <ResearchKit/ORKRecorder.h>
|
||||
#import <Availability.h>
|
||||
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
@@ -68,5 +68,5 @@ API_AVAILABLE(ios(12.0))
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#import "ORKRecorder_Internal.h"
|
||||
#import "HKSample+ORKJSONDictionary.h"
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
@interface ORKHealthClinicalTypeRecorder () {
|
||||
ORKDataLogger *_logger;
|
||||
@@ -234,3 +235,4 @@
|
||||
|
||||
@end
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -49,6 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
The `ORKHealthQuantityTypeRecorder` class represents a recorder for collecting real time sample data from HealthKit, such as heart rate, during
|
||||
an active task.
|
||||
*/
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
ORK_CLASS_AVAILABLE
|
||||
@interface ORKHealthQuantityTypeRecorder : ORKRecorder
|
||||
|
||||
@@ -76,5 +77,5 @@ ORK_CLASS_AVAILABLE
|
||||
outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#import "ORKRecorder_Internal.h"
|
||||
#import "HKSample+ORKJSONDictionary.h"
|
||||
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
@interface ORKHealthQuantityTypeRecorder () {
|
||||
ORKDataLogger *_logger;
|
||||
BOOL _isRecording;
|
||||
@@ -368,3 +368,4 @@ static const NSInteger _HealthAnchoredQueryLimit = 100;
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
#import "CLLocation+ORKJSONDictionary.h"
|
||||
|
||||
#import <ResearchKit/CLLocationManager+ResearchKit.h>
|
||||
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
|
||||
@@ -93,25 +95,25 @@
|
||||
}
|
||||
|
||||
self.locationManager = [self createLocationManager];
|
||||
|
||||
CLAuthorizationStatus status = kCLAuthorizationStatusNotDetermined;
|
||||
|
||||
if (@available(iOS 14.0, *)) {
|
||||
status = self.locationManager.authorizationStatus;
|
||||
} else {
|
||||
status = [CLLocationManager authorizationStatus];
|
||||
}
|
||||
|
||||
if (status == kCLAuthorizationStatusRestricted || status == kCLAuthorizationStatusNotDetermined) {
|
||||
[self.locationManager requestWhenInUseAuthorization];
|
||||
self.locationManager.delegate = self;
|
||||
|
||||
BOOL locationManagerAuthRequestsAllowed = YES;
|
||||
if ([CLLocationManager authorizationStatus] <= kCLAuthorizationStatusDenied) {
|
||||
locationManagerAuthRequestsAllowed = [self.locationManager ork_requestWhenInUseAuthorization];
|
||||
}
|
||||
|
||||
self.uptime = [NSProcessInfo processInfo].systemUptime;
|
||||
[self.locationManager startUpdatingLocation];
|
||||
[self.locationManager ork_startUpdatingLocation];
|
||||
|
||||
if (locationManagerAuthRequestsAllowed == NO) {
|
||||
// If we weren't able to perform auth requests, then ResearchKit was compiled with auth requests disabled
|
||||
// We won't be getting any callbacks about location changes, so might as well stop recording
|
||||
[self stop];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)doStopRecording {
|
||||
[self.locationManager stopUpdatingLocation];
|
||||
[self.locationManager ork_stopUpdatingLocation];
|
||||
self.locationManager.delegate = nil;
|
||||
self.locationManager = nil;
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
|
||||
|
||||
@import UIKit;
|
||||
#import "ORKCustomStepView_Internal.h"
|
||||
#import "ORKNormalizedReactionTimeStimulusView.h"
|
||||
#import "ORKRoundTappingButton.h"
|
||||
#import <ResearchKit/ORKCustomStepView_Internal.h>
|
||||
#import <ResearchKit/ORKNormalizedReactionTimeStimulusView.h>
|
||||
#import <ResearchKit/ORKRoundTappingButton.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
@import UIKit;
|
||||
#import "ORKCustomStepView_Internal.h"
|
||||
#import <ResearchKit/ORKCustomStepView_Internal.h>
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
|
||||
|
||||
@import UIKit;
|
||||
#import "ORKDefines.h"
|
||||
#import "ORKActiveStepViewController.h"
|
||||
#import <ResearchKit/ORKDefines.h>
|
||||
#import <ResearchKit/ORKActiveStepViewController.h>
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -31,10 +31,13 @@
|
||||
|
||||
|
||||
@import UIKit;
|
||||
@import HealthKit;
|
||||
#import <ResearchKit/ORKDefines.h>
|
||||
#import <Availability.h>
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -106,7 +109,9 @@ ORK_CLASS_AVAILABLE
|
||||
If your recorder requires or would benefit from read access to HealthKit at
|
||||
runtime during the task, return the appropriate set of `HKSampleType` objects.
|
||||
*/
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (nullable NSSet<HKObjectType *> *)requestedHealthKitTypesForReading;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@@ -355,6 +360,8 @@ ORK_CLASS_AVAILABLE
|
||||
of an `ORKActiveStep` object, include that step in a task, and present it with
|
||||
a task view controller.
|
||||
*/
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
ORK_CLASS_AVAILABLE
|
||||
@interface ORKHealthQuantityTypeRecorderConfiguration : ORKRecorderConfiguration
|
||||
|
||||
@@ -433,7 +440,7 @@ API_AVAILABLE(ios(12.0))
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/**
|
||||
The `ORKStreamingAudioRecorderConfiguration` class represents a configuration that records streaming
|
||||
audio data during an active step.
|
||||
|
||||
@@ -89,9 +89,12 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (NSSet<HKObjectType *> *)requestedHealthKitTypesForReading {
|
||||
return nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (ORKPermissionMask)requestedPermissionMask {
|
||||
return ORKPermissionNone;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright (c) 2023, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission. No license is granted to the trademarks of
|
||||
the copyright holders even if such marks are included in this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#import <CoreLocation/CLLocationManager.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface CLLocationManager (ResearchKit)
|
||||
|
||||
/**
|
||||
These categories on CLLocationManager provide ResearchKit code with a common way of requesting authorization that can be disabled by
|
||||
an Xcode build setting. Callers don't have to add compile-time conditional #if blocks. Instead callers should interpret return value of YES to mean
|
||||
the authorization request was made, and NO to mean the ResearchKit binary was built with CLLocationManager authorization request calls
|
||||
compiled out.
|
||||
|
||||
The impetus for this approach was to prevent apps using ResearchKit, but not ResearchKit's CoreLocation-powered features, from needlessly
|
||||
defining an NSLocationWhenInUseUsageDescription Info.plist entry to silence build errors.
|
||||
*/
|
||||
- (BOOL)ork_requestWhenInUseAuthorization;
|
||||
- (BOOL)ork_requestAlwaysAuthorization;
|
||||
|
||||
- (void)ork_startUpdatingLocation;
|
||||
- (void)ork_stopUpdatingLocation;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (c) 2023, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission. No license is granted to the trademarks of
|
||||
the copyright holders even if such marks are included in this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#import "CLLocationManager+ResearchKit.h"
|
||||
|
||||
#import "ORKDefines.h"
|
||||
|
||||
@implementation CLLocationManager (ResearchKit)
|
||||
|
||||
- (BOOL)ork_requestWhenInUseAuthorization {
|
||||
#if ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION
|
||||
[self requestWhenInUseAuthorization];
|
||||
return YES;
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)ork_requestAlwaysAuthorization {
|
||||
#if ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION
|
||||
[self requestAlwaysAuthorization];
|
||||
return YES;
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)ork_startUpdatingLocation {
|
||||
#if ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION
|
||||
[self startUpdatingLocation];
|
||||
#else
|
||||
// noop
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)ork_stopUpdatingLocation {
|
||||
#if ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION
|
||||
[self stopUpdatingLocation];
|
||||
#else
|
||||
// noop
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -43,7 +43,10 @@
|
||||
#import "ORKHealthAnswerFormat.h"
|
||||
#endif
|
||||
|
||||
@import HealthKit;
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
@import MapKit;
|
||||
@import Contacts;
|
||||
|
||||
@@ -93,6 +96,7 @@ static NSNumberFormatterStyle ORKNumberFormattingStyleConvert(ORKNumberFormattin
|
||||
NSMutableDictionary *_unitsTable;
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
@synthesize healthStore=_healthStore;
|
||||
|
||||
+ (instancetype)sourceWithHealthStore:(HKHealthStore *)healthStore {
|
||||
@@ -201,8 +205,10 @@ static NSNumberFormatterStyle ORKNumberFormattingStyleConvert(ORKNumberFormattin
|
||||
[healthStore executeQuery:sampleQuery];
|
||||
});
|
||||
}
|
||||
#endif // ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
- (void)fetchDefaultValueForAnswerFormat:(ORKAnswerFormat *)answerFormat handler:(void(^)(id defaultValue, NSError *error))handler {
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
HKObjectType *objectType = [answerFormat healthKitObjectType];
|
||||
BOOL handled = NO;
|
||||
if (objectType) {
|
||||
@@ -223,8 +229,13 @@ static NSNumberFormatterStyle ORKNumberFormattingStyleConvert(ORKNumberFormattin
|
||||
if (!handled) {
|
||||
handler(nil, nil);
|
||||
}
|
||||
#else
|
||||
handler(nil, nil);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
- (HKUnit *)defaultHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat {
|
||||
__block HKUnit *unit = [answerFormat healthKitUnit];
|
||||
HKObjectType *objectType = [answerFormat healthKitObjectType];
|
||||
@@ -267,9 +278,11 @@ static NSNumberFormatterStyle ORKNumberFormattingStyleConvert(ORKNumberFormattin
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
#endif // TARGET_OS_IOS
|
||||
|
||||
#pragma mark - ORKAnswerFormat
|
||||
|
||||
@@ -552,6 +565,7 @@ static NSNumberFormatterStyle ORKNumberFormattingStyleConvert(ORKNumberFormattin
|
||||
return NO;
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (HKObjectType *)healthKitObjectType {
|
||||
return nil;
|
||||
}
|
||||
@@ -571,6 +585,7 @@ static NSNumberFormatterStyle ORKNumberFormattingStyleConvert(ORKNumberFormattin
|
||||
- (void)setHealthKitUserUnit:(HKUnit *)unit {
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
- (ORKQuestionType)questionType {
|
||||
return ORKQuestionTypeNone;
|
||||
|
||||
@@ -29,18 +29,28 @@
|
||||
*/
|
||||
|
||||
|
||||
@import HealthKit;
|
||||
#import "ORKAnswerFormat_Private.h"
|
||||
#import <ResearchKit/ORKDefines.h>
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
#import <ResearchKit/ORKAnswerFormat_Private.h>
|
||||
#import "ORKChoiceAnswerFormatHelper.h"
|
||||
|
||||
@class ORKChoiceAnswerFormatHelper;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
BOOL ORKIsAnswerEmpty(_Nullable id answer);
|
||||
|
||||
#if TARGET_OS_IOS
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
NSString *ORKHKBiologicalSexString(HKBiologicalSex biologicalSex);
|
||||
NSString *ORKHKBloodTypeString(HKBloodType bloodType);
|
||||
#endif
|
||||
#endif // ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#endif // TARGET_OS_IOS
|
||||
|
||||
NSString *ORKQuestionTypeString(ORKQuestionType questionType);
|
||||
|
||||
// Need to mark these as designated initializers to avoid warnings once we designate the others.
|
||||
@@ -80,6 +90,7 @@ ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTextChoice)
|
||||
#if TARGET_OS_IOS
|
||||
- (BOOL)isHealthKitAnswerFormat;
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (nullable HKObjectType *)healthKitObjectType;
|
||||
- (nullable HKObjectType *)healthKitObjectTypeForAuthorization;
|
||||
|
||||
@@ -87,6 +98,7 @@ ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTextChoice)
|
||||
|
||||
@property (nonatomic, strong, nullable) HKUnit *healthKitUserUnit;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
- (nullable NSString *)localizedInvalidValueStringWithAnswerString:(nullable NSString *)text;
|
||||
|
||||
@@ -248,15 +260,17 @@ NSArray<Class> *ORKAllowableValueClasses(void);
|
||||
|
||||
@interface ORKAnswerDefaultSource : NSObject
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
+ (instancetype)sourceWithHealthStore:(HKHealthStore *)healthStore;
|
||||
- (instancetype)initWithHealthStore:(HKHealthStore *)healthStore NS_DESIGNATED_INITIALIZER;
|
||||
- (nullable HKUnit *)defaultHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat;
|
||||
- (void)updateHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat force:(BOOL)force;
|
||||
|
||||
@property (nonatomic, strong, readonly, nullable) HKHealthStore *healthStore;
|
||||
#endif
|
||||
|
||||
- (void)fetchDefaultValueForAnswerFormat:(nullable ORKAnswerFormat *)answerFormat handler:(void(^)(id defaultValue, NSError *error))handler;
|
||||
|
||||
- (nullable HKUnit *)defaultHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat;
|
||||
- (void)updateHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat force:(BOOL)force;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
|
||||
|
||||
@import UIKit;
|
||||
|
||||
#import "ORKDefaultFont.h"
|
||||
#import "ORKDefines.h"
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,9 +30,12 @@
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#import <ResearchKit/ORKDefines.h>
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -85,6 +88,8 @@ ORK_CLASS_AVAILABLE
|
||||
It cannot be initiated directly.
|
||||
Use `addHealthCollectorWithSampleType:`to add one to a `ORKDataCollectionManager`.
|
||||
*/
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
ORK_CLASS_AVAILABLE
|
||||
@interface ORKHealthCollector : ORKCollector
|
||||
|
||||
@@ -146,7 +151,7 @@ ORK_CLASS_AVAILABLE
|
||||
@property (copy, readonly) HKQueryAnchor *lastAnchor;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
ORKHealthCollector collects CMMotionActivity.
|
||||
|
||||
@@ -112,7 +112,7 @@ static NSString *const ItemIdentifierFormatWithTwoPlaceholders = @"org.researchk
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
@implementation ORKHealthCollector : ORKCollector
|
||||
|
||||
- (instancetype)initWithSampleType:(HKSampleType*)sampleType unit:(HKUnit*)unit startDate:(NSDate*)startDate {
|
||||
@@ -288,7 +288,7 @@ static NSString *const ItemIdentifierFormatWithTwoPlaceholders = @"org.researchk
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@implementation ORKMotionActivityCollector : ORKCollector
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
@end
|
||||
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
@protocol ORKHealthCollectable <NSObject>
|
||||
|
||||
- (HKSampleType *)sampleType;
|
||||
@@ -71,7 +72,7 @@
|
||||
@property (copy) HKQueryAnchor *lastAnchor;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@interface ORKMotionActivityCollector()
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time,
|
||||
until the data is accepted.
|
||||
*/
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (BOOL)healthCollector:(ORKHealthCollector *)collector didCollectSamples:(NSArray<HKSample *> *)samples;
|
||||
|
||||
/**
|
||||
@@ -73,7 +74,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
until the data is accepted.
|
||||
*/
|
||||
- (BOOL)healthCorrelationCollector:(ORKHealthCorrelationCollector *)collector didCollectCorrelations:(NSArray<HKCorrelation *> *)correlations;
|
||||
|
||||
#endif
|
||||
/**
|
||||
Method for delivering the collected motion activities.
|
||||
|
||||
@@ -145,6 +146,7 @@ ORK_CLASS_AVAILABLE
|
||||
|
||||
@return Initiated health collector.
|
||||
*/
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (ORKHealthCollector *)addHealthCollectorWithSampleType:(HKSampleType *)sampleType
|
||||
unit:(HKUnit *)unit
|
||||
startDate:(NSDate *)startDate
|
||||
@@ -166,6 +168,7 @@ ORK_CLASS_AVAILABLE
|
||||
units:(NSArray<HKUnit *> *)units
|
||||
startDate:(NSDate *)startDate
|
||||
error:(NSError * _Nullable *)error;
|
||||
#endif
|
||||
|
||||
/**
|
||||
Add a collector for motion activity.
|
||||
|
||||
@@ -33,8 +33,10 @@
|
||||
#import "ORKCollector_Internal.h"
|
||||
#import "ORKOperation.h"
|
||||
#import "ORKHelpers_Internal.h"
|
||||
#import <HealthKit/HealthKit.h>
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
// The file names for persisting the state of our collectors
|
||||
static NSString *const ORKDataCollectionPersistenceFileNamev1 = @".dataCollection.ork.data"; // pre-secureCoding
|
||||
@@ -45,9 +47,11 @@ static NSString *const ORKDataCollectionPersistenceFileNamev2 = @".dataCollecti
|
||||
NSOperationQueue *_operationQueue;
|
||||
NSString * _Nonnull _managedDirectory;
|
||||
NSArray<ORKCollector *> *_collectors;
|
||||
HKHealthStore *_healthStore;
|
||||
CMMotionActivityManager *_activityManager;
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
HKHealthStore *_healthStore;
|
||||
NSMutableArray<HKObserverQueryCompletionHandler> *_completionHandlers;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (instancetype)initWithPersistenceDirectoryURL:(NSURL *)directoryURL {
|
||||
@@ -119,12 +123,14 @@ static inline void dispatch_sync_if_not_on_queue(dispatch_queue_t queue, dispatc
|
||||
});
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (HKHealthStore *)healthStore {
|
||||
if (!_healthStore && [HKHealthStore isHealthDataAvailable]){
|
||||
_healthStore = [[HKHealthStore alloc] init];
|
||||
}
|
||||
return _healthStore;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (CMMotionActivityManager *)activityManager {
|
||||
if (!_activityManager && [CMMotionActivityManager isActivityAvailable]) {
|
||||
@@ -183,6 +189,7 @@ static inline void dispatch_sync_if_not_on_queue(dispatch_queue_t queue, dispatc
|
||||
_collectors = [collectors copy];
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (ORKHealthCollector *)addHealthCollectorWithSampleType:(HKSampleType*)sampleType unit:(HKUnit *)unit startDate:(NSDate *)startDate error:(NSError**)error {
|
||||
|
||||
if (!sampleType) {
|
||||
@@ -235,6 +242,7 @@ static inline void dispatch_sync_if_not_on_queue(dispatch_queue_t queue, dispatc
|
||||
|
||||
return healthCorrelationCollector;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (ORKMotionActivityCollector *)addMotionActivityCollectorWithStartDate:(NSDate *)startDate
|
||||
error:(NSError* __autoreleasing *)error {
|
||||
@@ -336,11 +344,12 @@ static inline void dispatch_sync_if_not_on_queue(dispatch_queue_t queue, dispatc
|
||||
[_delegate dataCollectionManagerDidCompleteCollection:self];
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
for (HKObserverQueryCompletionHandler handler in _completionHandlers) {
|
||||
handler();
|
||||
}
|
||||
[_completionHandlers removeAllObjects];
|
||||
|
||||
#endif
|
||||
return NO;
|
||||
}];
|
||||
}];
|
||||
|
||||
@@ -32,10 +32,11 @@
|
||||
#import "ORKDataCollectionManager.h"
|
||||
#import <CoreMotion/CoreMotion.h>
|
||||
|
||||
|
||||
@interface ORKDataCollectionManager ()
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
@property (nonatomic, strong, readonly) HKHealthStore *healthStore;
|
||||
#endif
|
||||
|
||||
@property (nonatomic, strong, readonly) CMMotionActivityManager *activityManager;
|
||||
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (NSSet<HKObjectType *> *)requestedHealthKitTypesForReading {
|
||||
NSMutableSet<HKObjectType *> *healthTypes = [NSMutableSet set];
|
||||
|
||||
@@ -194,7 +195,7 @@
|
||||
|
||||
return healthTypes.count ? healthTypes : nil;
|
||||
}
|
||||
|
||||
#endif
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -335,7 +335,10 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
|
||||
}
|
||||
|
||||
- (instancetype)ORKFormStepViewController_initWithResult:(ORKResult *)result {
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
_defaultSource = [ORKAnswerDefaultSource sourceWithHealthStore:[HKHealthStore new]];
|
||||
#endif
|
||||
|
||||
if (result) {
|
||||
NSAssert([result isKindOfClass:[ORKStepResult class]], @"Expect a ORKStepResult instance");
|
||||
|
||||
@@ -377,6 +380,7 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
[self updateAnsweredSections];
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
NSMutableSet *types = [NSMutableSet set];
|
||||
for (ORKFormItem *item in [self formItems]) {
|
||||
ORKAnswerFormat *format = [item answerFormat];
|
||||
@@ -404,7 +408,7 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
|
||||
if (!refreshDefaultsPending) {
|
||||
[self refreshDefaults];
|
||||
}
|
||||
|
||||
#endif
|
||||
// Reset skipped flag - result can now be non-empty
|
||||
_skipped = NO;
|
||||
|
||||
@@ -491,6 +495,8 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
|
||||
}
|
||||
|
||||
- (void)refreshDefaults {
|
||||
// defaults only come from HealthKit
|
||||
|
||||
NSArray *formItems = [self formItems];
|
||||
ORKAnswerDefaultSource *source = _defaultSource;
|
||||
ORKWeakTypeOf(self) weakSelf = self;
|
||||
@@ -516,10 +522,7 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
|
||||
ORKStrongTypeOf(weakSelf) strongSelf = weakSelf;
|
||||
[strongSelf updateDefaults:defaults];
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeAnswerForIdentifier:(NSString *)identifier {
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
@import HealthKit;
|
||||
#import <ResearchKit/ORKAnswerFormat.h>
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NSString *ORKBiologicalSexIdentifier NS_STRING_ENUM;
|
||||
@@ -62,6 +64,8 @@ ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierONegative;
|
||||
|
||||
You can use the HealthKit characteristic answer format to let users autofill information, such as their blood type or date of birth.
|
||||
*/
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
ORK_CLASS_AVAILABLE
|
||||
@interface ORKHealthKitCharacteristicTypeAnswerFormat : ORKAnswerFormat
|
||||
|
||||
@@ -213,6 +217,7 @@ included in the question result generated by form items or question steps
|
||||
- (NSString *)localizedUnitString;
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#import "ORKHealthAnswerFormat.h"
|
||||
|
||||
#import "ORKAnswerFormat_Internal.h"
|
||||
@@ -38,6 +37,7 @@
|
||||
#import "ORKQuestionResult_Private.h"
|
||||
#import "ORKResult.h"
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
#pragma mark - ORKHealthAnswerFormat
|
||||
|
||||
@@ -420,3 +420,4 @@ NSString *ORKHKBloodTypeString(HKBloodType bloodType) {
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,10 @@
|
||||
#import "ORKHealthKitPermissionType.h"
|
||||
#import "ORKHelpers_Internal.h"
|
||||
#import "ORKRequestPermissionView.h"
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
static NSString *const Symbol = @"heart.fill";
|
||||
static uint32_t const IconTintColor = 0xFF5E5E;
|
||||
@@ -77,6 +80,8 @@ static uint32_t const IconTintColor = 0xFF5E5E;
|
||||
}
|
||||
|
||||
- (void)checkHealthKitAuthorizationStatus {
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
if (![HKHealthStore isHealthDataAvailable]) {
|
||||
[self setState:ORKRequestPermissionsButtonStateNotSupported canContinue:YES];
|
||||
return;
|
||||
@@ -107,9 +112,12 @@ static uint32_t const IconTintColor = 0xFF5E5E;
|
||||
} else {
|
||||
[self setState:ORKRequestPermissionsButtonStateDefault canContinue:NO];
|
||||
}
|
||||
|
||||
#endif // ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
}
|
||||
|
||||
- (void)requestPermissionButtonPressed {
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
[[HKHealthStore new] requestAuthorizationToShareTypes:_sampleTypesToWrite readTypes:_objectTypesToRead completion:^(BOOL success, NSError * _Nullable error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
@@ -121,6 +129,7 @@ static uint32_t const IconTintColor = 0xFF5E5E;
|
||||
[self setState:ORKRequestPermissionsButtonStateConnected canContinue:YES];
|
||||
});
|
||||
}];
|
||||
#endif // ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
}
|
||||
|
||||
- (void)setState:(ORKRequestPermissionsButtonState)state canContinue:(BOOL)canContinue {
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
*/
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ORKOperation.h"
|
||||
#import "ORKDefines.h"
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
|
||||
@class ORKDataCollectionManager;
|
||||
@@ -47,3 +49,4 @@
|
||||
- (instancetype)initWithCollector:(ORKCollector<ORKHealthCollectable> *)collector mananger:(ORKDataCollectionManager *)manager;
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#import "ORKCollector_Internal.h"
|
||||
#import "ORKDataCollectionManager_Internal.h"
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
static NSUInteger const QueryLimitSize = 1000;
|
||||
|
||||
@@ -245,3 +246,4 @@ static NSUInteger const QueryLimitSize = 1000;
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
#import "ORKHelpers_Internal.h"
|
||||
#import "ORKRequestPermissionButton.h"
|
||||
|
||||
@import CoreLocation;
|
||||
#import <CoreLocation/CLLocationManagerDelegate.h>
|
||||
#import <ResearchKit/CLLocationManager+ResearchKit.h>
|
||||
|
||||
static NSString *const Symbol = @"location.circle";
|
||||
static const uint32_t IconLightTintColor = 0x50C878;
|
||||
@@ -114,7 +115,11 @@ static const uint32_t IconDarkTintColor = 0x00A36C;
|
||||
|
||||
// Request for always permission.
|
||||
- (void)requestPermissionButtonPressed {
|
||||
[self.locationManager requestAlwaysAuthorization];
|
||||
BOOL requestWasDelivered = [self.locationManager ork_requestAlwaysAuthorization];
|
||||
|
||||
// if the auth request was not delivered, that means ResearchKit was built with CoreLocation requests disabled
|
||||
// Presenting the location permission step in this case is probably programmer error
|
||||
NSAssert(requestWasDelivered, @"Tried to invoke -[CLLocationManager requestAlwaysAuthorization] but ResearchKit was compiled with CoreLocation authorization requests disabled. This is a programmer error. Check build settings for ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION");
|
||||
}
|
||||
|
||||
- (void)setState:(ORKRequestPermissionsButtonState)state canContinue:(BOOL)canContinue {
|
||||
|
||||
@@ -48,8 +48,9 @@
|
||||
#import "ORKHelpers_Internal.h"
|
||||
#import "ORKSkin.h"
|
||||
|
||||
@import MapKit;
|
||||
#import <ResearchKit/CLLocationManager+ResearchKit.h>
|
||||
|
||||
@import MapKit;
|
||||
|
||||
static const NSString *FormattedAddressLines = @"FormattedAddressLines";
|
||||
|
||||
@@ -294,7 +295,7 @@ static const NSString *FormattedAddressLines = @"FormattedAddressLines";
|
||||
_locationManager.delegate = self;
|
||||
}
|
||||
if (status == kCLAuthorizationStatusNotDetermined) {
|
||||
[_locationManager requestWhenInUseAuthorization];
|
||||
[_locationManager ork_requestWhenInUseAuthorization];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -441,8 +442,10 @@ static const NSString *FormattedAddressLines = @"FormattedAddressLines";
|
||||
|
||||
# pragma mark CLLocationManagerDelegate
|
||||
|
||||
- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
|
||||
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
|
||||
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
|
||||
[self loadCurrentLocationIfNecessary];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark MKMapViewDelegate
|
||||
|
||||
@@ -149,10 +149,10 @@ void ORKStepArrayAddStep(NSMutableArray *array, ORKStep *step) {
|
||||
@implementation ORKOrderedTask (ORKMakeTaskUtilities)
|
||||
|
||||
+ (NSArray<ORKRecorderConfiguration*>*)makeRecorderConfigurationsWithOptions:(ORKPredefinedTaskOption)options {
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
HKUnit *bpmUnit = [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]];
|
||||
HKQuantityType *heartRateType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
|
||||
|
||||
#endif
|
||||
NSMutableArray<ORKRecorderConfiguration*> *recorderConfigurations = [NSMutableArray arrayWithCapacity:5];
|
||||
|
||||
if (!(ORKPredefinedTaskOptionExcludePedometer & options)) {
|
||||
@@ -169,10 +169,13 @@ void ORKStepArrayAddStep(NSMutableArray *array, ORKStep *step) {
|
||||
if (!(ORKPredefinedTaskOptionExcludeLocation & options)) {
|
||||
[recorderConfigurations addObject:[[ORKLocationRecorderConfiguration alloc] initWithIdentifier:ORKLocationRecorderIdentifier]];
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
if (!(ORKPredefinedTaskOptionExcludeHeartRate & options)) {
|
||||
[recorderConfigurations addObject:[[ORKHealthQuantityTypeRecorderConfiguration alloc] initWithIdentifier:ORKHeartRateRecorderIdentifier
|
||||
healthQuantityType:heartRateType unit:bpmUnit]];
|
||||
}
|
||||
#endif
|
||||
return [recorderConfigurations copy];
|
||||
}
|
||||
|
||||
|
||||
@@ -80,12 +80,14 @@
|
||||
return ORKPermissionNone;
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (NSSet<HKObjectType *> *)requestedHealthKitTypesForReading {
|
||||
if ([self.pageTask respondsToSelector:@selector(requestedHealthKitTypesForReading)]) {
|
||||
return [self.pageTask requestedHealthKitTypesForReading];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
|
||||
#import <ResearchKit/ORKResult.h>
|
||||
|
||||
@import CoreLocation;
|
||||
#import <CoreLocation/CLLocation.h>
|
||||
|
||||
@import Contacts;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class CLCircularRegion;
|
||||
@class ORKQuestionStep;
|
||||
@class ORKFormItem;
|
||||
@class ORKFormStep;
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
#import "ORKLearnMoreItem.h"
|
||||
#endif
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_IOS
|
||||
ORKQuestionStepPresentationStyle const ORKQuestionStepPresentationStyleDefault = @"default";
|
||||
ORKQuestionStepPresentationStyle const ORKQuestionStepPresentationStylePlatter = @"platter";
|
||||
@@ -110,10 +114,12 @@ ORKQuestionStepPresentationStyle const ORKQuestionStepPresentationStylePlatter =
|
||||
return [impliedAnswerFormat isKindOfClass:[ORKTextAnswerFormat class]] && ![(ORKTextAnswerFormat *)impliedAnswerFormat multipleLines];
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (NSSet<HKObjectType *> *)requestedHealthKitTypesForReading {
|
||||
HKObjectType *objType = [[self answerFormat] healthKitObjectTypeForAuthorization];
|
||||
return (objType != nil) ? [NSSet setWithObject:objType] : nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -146,7 +146,9 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
|
||||
- (instancetype)initWithStep:(ORKStep *)step {
|
||||
self = [super initWithStep:step];
|
||||
if (self) {
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
_defaultSource = [ORKAnswerDefaultSource sourceWithHealthStore:[HKHealthStore new]];
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -452,8 +454,10 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
|
||||
}
|
||||
|
||||
- (void)requestAndRefreshDefaults {
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
NSMutableSet *types = [NSMutableSet set];
|
||||
ORKAnswerFormat *format = [[self questionStep] answerFormat];
|
||||
|
||||
HKObjectType *objType = [format healthKitObjectTypeForAuthorization];
|
||||
if (objType) {
|
||||
[types addObject:objType];
|
||||
@@ -476,6 +480,10 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
|
||||
if (!scheduledRefresh) {
|
||||
[self refreshDefaults];
|
||||
}
|
||||
#endif
|
||||
if (_tableView) {
|
||||
[_tableView reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
||||
@@ -30,7 +30,12 @@
|
||||
|
||||
|
||||
@import Foundation;
|
||||
@import HealthKit;
|
||||
|
||||
#import <ResearchKit/ORKDefines.h>
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
#import <ResearchKit/ORKTypes.h>
|
||||
|
||||
@@ -245,6 +250,7 @@ requests access to these HealthKit types.
|
||||
|
||||
See also: `requestedHealthKitTypesForWriting`.
|
||||
*/
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
@property (nonatomic, copy, readonly, nullable) NSSet<HKObjectType *> *requestedHealthKitTypesForReading;
|
||||
|
||||
/**
|
||||
@@ -257,6 +263,7 @@ requests access to these HealthKit types.
|
||||
See also: `requestedHealthKitTypesForReading`.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSSet<HKObjectType *> *requestedHealthKitTypesForWriting;
|
||||
#endif
|
||||
|
||||
/**
|
||||
The set of permissions requested by the task.
|
||||
|
||||
@@ -61,7 +61,8 @@
|
||||
|
||||
@import AVFoundation;
|
||||
@import CoreMotion;
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
#import <CoreLocation/CLLocationManagerDelegate.h>
|
||||
#import <ResearchKit/CLLocationManager+ResearchKit.h>
|
||||
|
||||
typedef void (^_ORKLocationAuthorizationRequestHandler)(BOOL success);
|
||||
|
||||
@@ -100,28 +101,22 @@ typedef void (^_ORKLocationAuthorizationRequestHandler)(BOOL success);
|
||||
}
|
||||
|
||||
_started = YES;
|
||||
|
||||
NSString *allowedWhenInUse = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"];
|
||||
NSString *allowedAlways = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysAndWhenInUseUsageDescription"];
|
||||
NSString *whenInUseKey = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"];
|
||||
NSString *alwaysKey = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysAndWhenInUseUsageDescription"];
|
||||
|
||||
if (_manager) {
|
||||
CLAuthorizationStatus status = kCLAuthorizationStatusNotDetermined;
|
||||
|
||||
if (@available(iOS 14.0, *)) {
|
||||
status = _manager.authorizationStatus;
|
||||
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
|
||||
if ((status == kCLAuthorizationStatusNotDetermined) && (whenInUseKey || alwaysKey)) {
|
||||
BOOL requestWasDelivered = YES;
|
||||
if (alwaysKey) {
|
||||
requestWasDelivered = [_manager ork_requestAlwaysAuthorization];
|
||||
} else {
|
||||
status = [CLLocationManager authorizationStatus];
|
||||
requestWasDelivered = [_manager ork_requestWhenInUseAuthorization];
|
||||
}
|
||||
|
||||
if ((status == kCLAuthorizationStatusNotDetermined) && (allowedWhenInUse || allowedAlways)) {
|
||||
if (allowedAlways) {
|
||||
[_manager requestAlwaysAuthorization];
|
||||
} else {
|
||||
[_manager requestWhenInUseAuthorization];
|
||||
}
|
||||
} else {
|
||||
[self finishWithResult:(status != kCLAuthorizationStatusDenied)];
|
||||
if (requestWasDelivered == NO) {
|
||||
[self finishWithResult:NO];
|
||||
}
|
||||
} else {
|
||||
[self finishWithResult:(status != kCLAuthorizationStatusDenied)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,18 +127,10 @@ typedef void (^_ORKLocationAuthorizationRequestHandler)(BOOL success);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
|
||||
CLAuthorizationStatus status = kCLAuthorizationStatusNotDetermined;
|
||||
|
||||
if (@available(iOS 14.0, *)) {
|
||||
status = manager.authorizationStatus;
|
||||
} else {
|
||||
status = [CLLocationManager authorizationStatus];
|
||||
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
|
||||
if (_handler && _started && status != kCLAuthorizationStatusNotDetermined) {
|
||||
[self finishWithResult:(status != kCLAuthorizationStatusDenied)];
|
||||
}
|
||||
|
||||
if (_started && status != kCLAuthorizationStatusNotDetermined) {
|
||||
[self finishWithResult:(status != kCLAuthorizationStatusDenied)];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -340,16 +327,24 @@ static NSString *const _ChildNavigationControllerRestorationKey = @"childNavigat
|
||||
writeTypes:(NSSet *)writeTypes
|
||||
handler:(void (^)(void))handler {
|
||||
NSParameterAssert(handler != nil);
|
||||
if ((![HKHealthStore isHealthDataAvailable]) || (!readTypes && !writeTypes)) {
|
||||
BOOL needsHealthKitAuthRequest = NO;
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
needsHealthKitAuthRequest = ([HKHealthStore isHealthDataAvailable]);
|
||||
needsHealthKitAuthRequest = needsHealthKitAuthRequest && ((readTypes != nil) || (writeTypes != nil));
|
||||
#endif
|
||||
|
||||
if (needsHealthKitAuthRequest == NO) {
|
||||
_requestedHealthTypesForRead = nil;
|
||||
_requestedHealthTypesForWrite = nil;
|
||||
handler();
|
||||
dispatch_async(dispatch_get_main_queue(), handler);
|
||||
return;
|
||||
}
|
||||
|
||||
_requestedHealthTypesForRead = readTypes;
|
||||
_requestedHealthTypesForWrite = writeTypes;
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
__block HKHealthStore *healthStore = [HKHealthStore new];
|
||||
[healthStore requestAuthorizationToShareTypes:writeTypes readTypes:readTypes completion:^(BOOL success, NSError *error) {
|
||||
ORK_Log_Error("Health access: error=%@", error);
|
||||
@@ -358,6 +353,7 @@ static NSString *const _ChildNavigationControllerRestorationKey = @"childNavigat
|
||||
// Clear self-ref.
|
||||
healthStore = nil;
|
||||
}];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)requestPedometerAccessWithHandler:(void (^)(BOOL success))handler {
|
||||
@@ -443,6 +439,7 @@ static NSString *const _ChildNavigationControllerRestorationKey = @"childNavigat
|
||||
return;
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
NSSet *readTypes = nil;
|
||||
if ([self.task respondsToSelector:@selector(requestedHealthKitTypesForReading)]) {
|
||||
readTypes = [self.task requestedHealthKitTypesForReading];
|
||||
@@ -452,6 +449,7 @@ static NSString *const _ChildNavigationControllerRestorationKey = @"childNavigat
|
||||
if ([self.task respondsToSelector:@selector(requestedHealthKitTypesForWriting)]) {
|
||||
writeTypes = [self.task requestedHealthKitTypesForWriting];
|
||||
}
|
||||
#endif
|
||||
|
||||
ORKPermissionMask permissions = [self desiredPermissions];
|
||||
|
||||
@@ -459,12 +457,14 @@ static NSString *const _ChildNavigationControllerRestorationKey = @"childNavigat
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
ORK_Log_Debug("Requesting health access");
|
||||
[self requestHealthStoreAccessWithReadTypes:readTypes
|
||||
writeTypes:writeTypes
|
||||
handler:^{
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
#endif
|
||||
});
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
if (permissions & ORKPermissionCoreMotionAccelerometer) {
|
||||
@@ -1585,8 +1585,15 @@ static NSString *const _ORKProgressMode = @"progressMode";
|
||||
}
|
||||
|
||||
if ([_task respondsToSelector:@selector(stepWithIdentifier:)]) {
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
_requestedHealthTypesForRead = [coder decodeObjectOfClasses:[NSSet setWithArray:@[NSSet.self, HKObjectType.self]] forKey:_ORKRequestedHealthTypesForReadRestoreKey];
|
||||
_requestedHealthTypesForWrite = [coder decodeObjectOfClasses:[NSSet setWithArray:@[NSSet.self, HKObjectType.self]] forKey:_ORKRequestedHealthTypesForWriteRestoreKey];
|
||||
#else
|
||||
_requestedHealthTypesForRead = nil;
|
||||
_requestedHealthTypesForWrite = nil;
|
||||
#endif
|
||||
|
||||
_presentedDate = [coder decodeObjectOfClass:[NSDate class] forKey:_ORKPresentedDate];
|
||||
_lastBeginningInstructionStepIdentifier = [coder decodeObjectOfClass:[NSString class] forKey:_ORKLastBeginningInstructionStepIdentifierKey];
|
||||
|
||||
|
||||
@@ -32,7 +32,10 @@
|
||||
#import <ResearchKit/ORKTaskViewController_Private.h>
|
||||
#import <ResearchKit/ORKReviewStepViewController.h>
|
||||
#import <ResearchKit/ORKActiveStep_Internal.h>
|
||||
@import HealthKit;
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
#import <HealthKit/HealthKit.h>
|
||||
#endif
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
|
||||
if(choiceOther.textViewStartsHidden) {
|
||||
if(choiceCell.textView.text.length <= 0) {
|
||||
shouldHideTextView = choiceCell.isSelected == NO;
|
||||
shouldHideTextView = (choiceCell.isCellSelected == NO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +170,9 @@
|
||||
if ([textChoice isKindOfClass:[ORKTextChoiceOther class]] && [touchedCell isKindOfClass:[ORKChoiceOtherViewCell class]]) {
|
||||
ORKTextChoiceOther *otherTextChoice = (ORKTextChoiceOther *)textChoice;
|
||||
ORKChoiceOtherViewCell *touchedOtherCell = (ORKChoiceOtherViewCell *)touchedCell;
|
||||
if (otherTextChoice.textViewInputOptional || touchedOtherCell.textView.text.length > 0) {
|
||||
[touchedOtherCell setCellSelected:YES highlight:NO];
|
||||
}
|
||||
[self updateTextViewForChoiceOtherCell:touchedOtherCell withTextChoiceOther:otherTextChoice];
|
||||
if (!otherTextChoice.textViewInputOptional && otherTextChoice.textViewText.length <= 0) {
|
||||
return;
|
||||
|
||||
@@ -79,7 +79,6 @@ struct TextChoiceView: View {
|
||||
var dividerPadding: CGFloat = 20
|
||||
dividerPadding += (imageWidth + 16)
|
||||
|
||||
|
||||
return dividerPadding
|
||||
}
|
||||
|
||||
|
||||
@@ -25,16 +25,43 @@ SYSTEM_FRAMEWORK_SEARCH_PATHS = $(inherited)
|
||||
SYSTEM_HEADER_SEARCH_PATHS = $(inherited)
|
||||
CLANG_STATIC_ANALYZER_MODE = deep
|
||||
|
||||
ORK_FRAMEWORK_VERSION_NUMBER = 2.2.15
|
||||
ORK_FRAMEWORK_VERSION_NUMBER = 2.2.16
|
||||
|
||||
ORK_FRAMEWORK_BUILD_NUMBER = $(ORK_FRAMEWORK_BUILD_NUMBER_CI_$(CI)) // ORK_FRAMEWORK_BUILD_NUMBER_CI_TRUE or ORK_FRAMEWORK_BUILD_NUMBER_CI_
|
||||
ORK_FRAMEWORK_BUILD_NUMBER_CI_TRUE = $(CI_BUILD_NUMBER)
|
||||
ORK_FRAMEWORK_BUILD_NUMBER_CI_FALSE = $(ORK_FRAMEWORK_VERSION_NUMBER) // When not building in CI, assume build and version number are the same
|
||||
ORK_FRAMEWORK_BUILD_NUMBER_CI_ = $(ORK_FRAMEWORK_BUILD_NUMBER_CI_FALSE)
|
||||
|
||||
// Control whether ResearchKit compiles out CLLocationManager calls that would request authorization for location
|
||||
// ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=0 compiles out the feature
|
||||
// ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=1 compiles RK with the feature intact
|
||||
ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS = $(ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS_$(ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION))
|
||||
ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS_0 = ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=0
|
||||
ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS_1 = ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=1
|
||||
|
||||
// Some CLLocationManager API calls would trigger authorization to use location. The presence of those
|
||||
// API calls in ResearchKit **at compile time** mean apps that link ResearchKit also need Info.plist entries
|
||||
// for NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription.
|
||||
// If your app doesn't use ORKLocationRecorder and doesn't specify these Info.plist strings, disable
|
||||
// ResearchKit's CLLocationManager authorization
|
||||
ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION = 1
|
||||
|
||||
// Some HealthKit API calls used within the framework require your app to disclose using HealthKit and provide a reason during app store review.
|
||||
// If your app does not use HealthKit or any of the ResearchKit HealthKit APIs, disable ResearchKit's HealthKit authorization.
|
||||
ORK_FEATURE_HEALTHKIT_AUTHORIZATION = 1
|
||||
|
||||
// GCC Preprocessor definitions
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC = $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_$(ORK_FEATURE_HEALTHKIT_AUTHORIZATION))
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_0 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION=0
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_1 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION=1
|
||||
|
||||
// Swift active compilation conditions
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT = $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_$(ORK_FEATURE_HEALTHKIT_AUTHORIZATION))
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_0 =
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_1 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
#include? "samples/ORKCatalog/ResearchKit-Shared.xcconfig"
|
||||
#include? "../xcconfig/ResearchKit-Shared.xcconfig"
|
||||
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(ORK_GCC_PREPROCESSOR_DEFINITIONS)
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) GLES_SILENCE_DEPRECATION=1 $(ORK_GCC_PREPROCESSOR_DEFINITIONS) $(ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS) $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC)
|
||||
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// ResearchKitTests-Debug.xcconfig
|
||||
//
|
||||
|
||||
#include "ResearchKitTests-Shared.xcconfig"
|
||||
|
||||
SWIFT_OBJC_BRIDGING_HEADER = ResearchKitTests/ResearchKitTests-Bridging-Header.h
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// ResearchKitTests-Shared.xcconfig
|
||||
//
|
||||
|
||||
CLANG_CXX_LANGUAGE_STANDARD = gnu++0x
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99
|
||||
GCC_WARN_SHADOW = NO
|
||||
INFOPLIST_FILE = ResearchKitTests/Info.plist
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.researchkit.$(PRODUCT_NAME:rfc1034identifier)
|
||||
PRODUCT_NAME = $(TARGET_NAME)
|
||||
SWIFT_VERSION = 5.0
|
||||
|
||||
// Control whether ResearchKitTests expect CLLocationManager calls requesting authorization for location
|
||||
// ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=0 compiles out the feature
|
||||
// ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=1 compiles RK with the feature intact
|
||||
ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS = $(ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS_$(ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION))
|
||||
ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS_0 = ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=0
|
||||
ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS_1 = ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=1
|
||||
|
||||
// Some CLLocationManager API calls would trigger authorization to use location. The presence of those
|
||||
// API calls in ResearchKit **at compile time** mean apps that link ResearchKit also need Info.plist entries
|
||||
// for NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription.
|
||||
// If your app doesn't use ORKLocationRecorder and doesn't specify these Info.plist strings, disable
|
||||
// ResearchKit's CLLocationManager authorization
|
||||
ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION = 1
|
||||
|
||||
// Some HealthKit API calls used within the framework require your app to disclose using HealthKit and provide a reason during app store review.
|
||||
// If your app does not use HealthKit or any of the ResearchKit HealthKit APIs, disable ResearchKit's HealthKit authorization.
|
||||
ORK_FEATURE_HEALTHKIT_AUTHORIZATION = 1
|
||||
|
||||
// GCC Preprocessor definitions
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC = $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_$(ORK_FEATURE_HEALTHKIT_AUTHORIZATION))
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_0 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION=0
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_1 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION=1
|
||||
|
||||
// Swift active compilation conditions
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT = $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_$(ORK_FEATURE_HEALTHKIT_AUTHORIZATION))
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_0 =
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_1 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
#include? "../xcconfig/ResearchKit-Shared.xcconfig"
|
||||
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) GLES_SILENCE_DEPRECATION=1 $(ORK_GCC_PREPROCESSOR_DEFINITIONS) $(ORK_FEATURE_CLLOCATIONMANAGER_DEFINITIONS) $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC)
|
||||
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT)
|
||||
@@ -183,3 +183,6 @@
|
||||
|
||||
#import <ResearchKit/ORKLearnMoreView.h>
|
||||
#import <ResearchKit/ORKBodyContainerView.h>
|
||||
// Class extensions
|
||||
#import <ResearchKit/CLLocationManager+ResearchKit.h>
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
#import <ResearchKit/ORKRequestPermissionsStep.h>
|
||||
#import <ResearchKit/ORK3DModelStep.h>
|
||||
|
||||
|
||||
#import <ResearchKit/ORKTask.h>
|
||||
#import <ResearchKit/ORKOrderedTask.h>
|
||||
#import <ResearchKit/ORKOrderedTask+ORKPredefinedActiveTask.h>
|
||||
|
||||
@@ -1509,6 +1509,7 @@
|
||||
XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:1] value], [NSNumber numberWithInteger:2]);
|
||||
}
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (void)testHealthKitCharacteristicTypeAnswerFormat {
|
||||
|
||||
HKCharacteristicType *biologicalSex = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex];
|
||||
@@ -1596,6 +1597,7 @@
|
||||
XCTAssertEqual([answerFormat numericAnswerStyle], ORKNumericAnswerStyleInteger);
|
||||
XCTAssertEqual([answerFormat quantityType], calories);
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)testDateAnswerFormat {
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
@implementation ORKHKSampleTests
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
- (void)testHKSampleSerialization {
|
||||
NSDate *d1 = [NSDate dateWithTimeIntervalSinceReferenceDate:0];
|
||||
NSDate *d2 = [NSDate dateWithTimeInterval:10 sinceDate:d1];
|
||||
@@ -107,5 +108,5 @@
|
||||
XCTAssertTrue([dict[@"objects"] containsObject:dd], @"");
|
||||
XCTAssertTrue([dict[@"objects"] containsObject:ds], @"");
|
||||
}
|
||||
|
||||
#endif
|
||||
@end
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
import XCTest
|
||||
import ResearchKit.Private
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
final class ORKHealthKitQuestionStepViewControllerTests: XCTestCase {
|
||||
var testController: ORKStepViewController!
|
||||
var step: ORKStep!
|
||||
@@ -131,4 +131,4 @@ extension ORKHealthKitQuestionStepViewControllerTests: ORKStepViewControllerDele
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -431,8 +431,26 @@ static const NSInteger kNumberOfSamples = 5;
|
||||
}
|
||||
|
||||
[recorder stop];
|
||||
[self checkResult];
|
||||
|
||||
// when location features are compiled out, make sure that the "ork_" wrapper functions are
|
||||
// returning false, but don't bother doing the checkResult step
|
||||
#if !ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION
|
||||
// when location auth is 0, the [recorder start] earlier immediately stops, which zeros
|
||||
// the locationManager property. So we would expect currentLocationManager == nil
|
||||
XCTAssertNil(currentLocationManager, @"ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION=0: expected recorder's location manager to be nil");
|
||||
|
||||
// make a one-time-use locationManager that we test ork_ wrappers with
|
||||
{
|
||||
CLLocationManager *locationManager = [(ORKMockLocationRecorder *)recorder createLocationManager];
|
||||
XCTAssertNotNil(locationManager);
|
||||
XCTAssertFalse([locationManager ork_requestWhenInUseAuthorization]);
|
||||
XCTAssertFalse([locationManager ork_requestAlwaysAuthorization]);
|
||||
}
|
||||
|
||||
#else
|
||||
[self checkResult];
|
||||
#endif // ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION
|
||||
|
||||
for (NSDictionary *sample in _items) {
|
||||
|
||||
XCTAssertTrue(ork_doubleEqual(altitude, ((NSNumber *)sample[@"altitude"]).doubleValue), @"");
|
||||
@@ -621,7 +639,7 @@ static const NSInteger kNumberOfSamples = 5;
|
||||
}
|
||||
|
||||
- (void)testHealthQuantityTypeRecorder {
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
HKUnit *bpmUnit = [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]];
|
||||
HKQuantityType *hbQuantityType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
|
||||
ORKHealthQuantityTypeRecorderConfiguration *recorderConfiguration = [[ORKHealthQuantityTypeRecorderConfiguration alloc] initWithIdentifier:@"healtQuantityTypeRecorder" healthQuantityType:hbQuantityType unit:bpmUnit];
|
||||
@@ -629,6 +647,7 @@ static const NSInteger kNumberOfSamples = 5;
|
||||
ORKHealthQuantityTypeRecorder *recorder = (ORKHealthQuantityTypeRecorder *)[self createRecorder:recorderConfiguration];
|
||||
|
||||
XCTAssertTrue([recorder isKindOfClass:recorderClass], @"");
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -204,13 +204,14 @@
|
||||
// create the task as if we were to present it
|
||||
ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc] initWithTask:task taskRunUUID:nil];
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
// Trigger requestHealth access to fill in the read/write types ivars
|
||||
NSSet *readTypes = [NSSet setWithObjects:[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate], nil];
|
||||
NSSet *writeTypes = [NSSet setWithObjects:[HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierBloating], nil];
|
||||
[taskViewController requestHealthStoreAccessWithReadTypes:readTypes writeTypes:writeTypes handler:^(){
|
||||
// intentionally left empty
|
||||
}];
|
||||
|
||||
#endif
|
||||
// viewWillAppear fills in the _managedStepIdentifiers in the taskViewController
|
||||
[taskViewController viewWillAppear:false];
|
||||
|
||||
@@ -244,10 +245,11 @@
|
||||
ORKResultTestsHelper *taskDelegate = [[ORKResultTestsHelper alloc] init];
|
||||
ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc] initWithTask:task restorationData:encodedTaskViewControllerData delegate:taskDelegate error:nil];
|
||||
|
||||
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
// confirm the read/write HK type info made it across the encode/decode bridge
|
||||
XCTAssertEqualObjects([taskViewController requestedHealthTypesForRead], [NSSet setWithObject:[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]]);
|
||||
XCTAssertEqualObjects([taskViewController requestedHealthTypesForWrite], [NSSet setWithObject:[HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierBloating]]);
|
||||
|
||||
#endif
|
||||
ORKStepResult *stepResult = (ORKStepResult *)[[[taskViewController result] results] firstObject];
|
||||
NSArray<ORKQuestionResult*> *questionResults = (NSArray<ORKQuestionResult*> *)[stepResult results];
|
||||
XCTAssertEqual([questionResults count], 3);
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
03F7FD9F23959DD500432EF6 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F7FD9E23959DD500432EF6 /* SceneDelegate.swift */; };
|
||||
0B6CB32728B577640092E993 /* Bundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6CB32628B577640092E993 /* Bundle+Extensions.swift */; };
|
||||
0BF63B3D2BC0977A00546F58 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BF63B3C2BC0977A00546F58 /* HealthKit.framework */; };
|
||||
3C39E45E2950EFAD00BD96F6 /* ORKCatalog-Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 3C39E45D2950EFAD00BD96F6 /* ORKCatalog-Shared.xcconfig */; };
|
||||
3E39B9FB1ABF682D00C2ABE5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3E39B9F91ABF682D00C2ABE5 /* Main.storyboard */; };
|
||||
3E39B9FE1ABF683700C2ABE5 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3E39B9FC1ABF683700C2ABE5 /* LaunchScreen.xib */; };
|
||||
3E39BA001ABF683F00C2ABE5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3E39B9FF1ABF683F00C2ABE5 /* Images.xcassets */; };
|
||||
3ED967B81AC13D37007E2D83 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ED967BA1AC13D37007E2D83 /* Localizable.strings */; };
|
||||
863CCD821ACF545E009FD3B4 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 863CCD811ACF545E009FD3B4 /* HealthKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
86B89AA51AB2C0A5001626A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86B89A9C1AB2C0A5001626A4 /* AppDelegate.swift */; };
|
||||
9622283924F04DBF0056E74D /* TaskScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622283824F04DBF0056E74D /* TaskScreen.swift */; };
|
||||
9622283B24F04DFE0056E74D /* CommonElements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622283A24F04DFE0056E74D /* CommonElements.swift */; };
|
||||
@@ -60,6 +60,7 @@
|
||||
/* Begin PBXFileReference section */
|
||||
03F7FD9E23959DD500432EF6 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
0B6CB32628B577640092E993 /* Bundle+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Extensions.swift"; sourceTree = "<group>"; };
|
||||
0BF63B3C2BC0977A00546F58 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
|
||||
246DF9FF1BEADFDF00591E9A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
246DFA021BEAE01700591E9A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
246DFA031BEAE02100591E9A /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
@@ -104,7 +105,6 @@
|
||||
3E39B9FD1ABF683700C2ABE5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
3E39B9FF1ABF683F00C2ABE5 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
3ED967B91AC13D37007E2D83 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
863CCD811ACF545E009FD3B4 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
|
||||
863CCD831ACF545E009FD3B4 /* ORKCatalog.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = ORKCatalog.entitlements; sourceTree = "<group>"; };
|
||||
869230BE1AAA890A00BFE11B /* ORKCatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORKCatalog.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
86B89A981AB2C0A5001626A4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
@@ -135,7 +135,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BC2A3CD91C58F1CA00DA64B7 /* ResearchKit.framework in Frameworks */,
|
||||
863CCD821ACF545E009FD3B4 /* HealthKit.framework in Frameworks */,
|
||||
0BF63B3D2BC0977A00546F58 /* HealthKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -254,8 +254,8 @@
|
||||
BC2A3C9E1C58E81500DA64B7 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0BF63B3C2BC0977A00546F58 /* HealthKit.framework */,
|
||||
BC2A3CD81C58F1CA00DA64B7 /* ResearchKit.framework */,
|
||||
863CCD811ACF545E009FD3B4 /* HealthKit.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// ORKCatalog-Shared.xcconfig
|
||||
//
|
||||
|
||||
ORK_CATALOG_VERSION_NUMBER = 2.2.15
|
||||
ORK_CATALOG_VERSION_NUMBER = 2.2.16
|
||||
|
||||
ORK_CATALOG_BUILD_NUMBER = $(ORK_CATALOG_BUILD_NUMBER_CI_$(CI)) // ORK_CATALOG_BUILD_NUMBER_CI_TRUE or ORK_CATALOG_BUILD_NUMBER_CI_
|
||||
ORK_CATALOG_BUILD_NUMBER_CI_TRUE = $(CI_BUILD_NUMBER) // if CI_BUILD_NUMBER is defined (presumably by CI) just use it
|
||||
@@ -15,3 +15,19 @@ ORK_CATALOG_BUNDLE_ID = $(ORK_CATALOG_BUNDLE_ID_CI_$(USE_CI)) // ORK_CATALOG_BUN
|
||||
ORK_CATALOG_BUNDLE_ID_CI_TRUE = $(USE_CI_BUNDLE_ID)$(ORK_CATALOG_CI_BUNDLE_ID_SUFFIX) // if CI_BUNDLE_ID is defined (presumably by CI) just use it, allow appending an optional suffix
|
||||
ORK_CATALOG_BUNDLE_ID_CI_FALSE = $(ORK_CATALOG_BUNDLE_ID_BASE) // when not in CI, use the Base bundle ID
|
||||
ORK_CATALOG_BUNDLE_ID_CI_ = $(ORK_CATALOG_BUNDLE_ID_CI_FALSE)
|
||||
|
||||
ORK_FEATURE_HEALTHKIT_AUTHORIZATION = 1
|
||||
|
||||
// GCC Preprocessor definitions
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC = $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_$(ORK_FEATURE_HEALTHKIT_AUTHORIZATION))
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_0 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION=0
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC_1 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION=1
|
||||
|
||||
// Swift active compilation conditions
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT = $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_$(ORK_FEATURE_HEALTHKIT_AUTHORIZATION))
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_0 =
|
||||
ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT_1 = ORK_FEATURE_HEALTHKIT_AUTHORIZATION
|
||||
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_GCC)
|
||||
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) $(ORK_FEATURE_HEALTHKIT_DEFINITIONS_SWIFT)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.healthkit</key>
|
||||
<true/>
|
||||
<key>com.apple.developer.healthkit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -140,7 +140,7 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
/// Returns an array of all the task list row enum cases.
|
||||
static var sections: [ TaskListRowSection ] {
|
||||
|
||||
let defaultSections = [
|
||||
var defaultSections = [
|
||||
TaskListRowSection(title: "Surveys", rows:
|
||||
[
|
||||
.form,
|
||||
@@ -261,10 +261,8 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
|
||||
case .weightQuestion:
|
||||
return NSLocalizedString("Weight Question", comment: "")
|
||||
|
||||
case .healthQuantity:
|
||||
return NSLocalizedString("Health Quantity Question", comment: "")
|
||||
|
||||
case .imageChoiceQuestion:
|
||||
return NSLocalizedString("Image Choice Question", comment: "")
|
||||
|
||||
@@ -1190,7 +1188,7 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
let step3NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.heightQuestionStep3) + "NonOptional", title: NSLocalizedString("Height", comment: ""), question: exampleQuestionText, answer: answerFormat3)
|
||||
step3NonOptional.text = "USC system (Non Optional)"
|
||||
step3NonOptional.isOptional = false
|
||||
|
||||
|
||||
let answerFormat4 = ORKHealthKitQuantityTypeAnswerFormat(quantityType: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!, unit: HKUnit.meterUnit(with: .centi), style: .decimal)
|
||||
|
||||
let step4 = ORKQuestionStep(identifier: String(describing: Identifier.heightQuestionStep4), title: NSLocalizedString("Height", comment: ""), question: exampleQuestionText, answer: answerFormat4)
|
||||
@@ -1207,80 +1205,78 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
/// This task demonstrates a question asking for the user weight.
|
||||
private var weightQuestionTask: ORKTask {
|
||||
let answerFormat1 = ORKAnswerFormat.weightAnswerFormat()
|
||||
|
||||
let step1 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep1), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat1)
|
||||
|
||||
step1.text = "Local system, default precision"
|
||||
|
||||
let step1NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep1) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat1)
|
||||
|
||||
step1NonOptional.text = "Local system, default precision (nonOptional)"
|
||||
step1NonOptional.isOptional = false
|
||||
|
||||
let answerFormat2 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric)
|
||||
|
||||
let step2 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep2), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat2)
|
||||
|
||||
step2.text = "Metric system, default precision"
|
||||
|
||||
let step2NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep2) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat2)
|
||||
|
||||
step2NonOptional.text = "Metric system, default precision (nonOptional)"
|
||||
step2NonOptional.isOptional = false
|
||||
|
||||
let answerFormat3 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric, numericPrecision: ORKNumericPrecision.low, minimumValue: ORKDoubleDefaultValue, maximumValue: ORKDoubleDefaultValue, defaultValue: ORKDoubleDefaultValue)
|
||||
|
||||
let step3 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep3), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat3)
|
||||
|
||||
step3.text = "Metric system, low precision"
|
||||
|
||||
let step1 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep1), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat1)
|
||||
|
||||
step1.text = "Local system, default precision"
|
||||
|
||||
let step1NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep1) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat1)
|
||||
|
||||
step1NonOptional.text = "Local system, default precision (nonOptional)"
|
||||
step1NonOptional.isOptional = false
|
||||
|
||||
let answerFormat2 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric)
|
||||
|
||||
let step2 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep2), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat2)
|
||||
|
||||
step2.text = "Metric system, default precision"
|
||||
|
||||
let step2NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep2) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat2)
|
||||
|
||||
step2NonOptional.text = "Metric system, default precision (nonOptional)"
|
||||
step2NonOptional.isOptional = false
|
||||
|
||||
let answerFormat3 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric, numericPrecision: ORKNumericPrecision.low, minimumValue: ORKDoubleDefaultValue, maximumValue: ORKDoubleDefaultValue, defaultValue: ORKDoubleDefaultValue)
|
||||
|
||||
let step3 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep3), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat3)
|
||||
|
||||
step3.text = "Metric system, low precision"
|
||||
|
||||
let step3NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep3) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat3)
|
||||
step3NonOptional.text = "Metric system, low precision (nonOptional)"
|
||||
step3NonOptional.isOptional = false
|
||||
|
||||
let answerFormat4 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric, numericPrecision: ORKNumericPrecision.high, minimumValue: 20.0, maximumValue: 100.0, defaultValue: 45.50)
|
||||
|
||||
let step4 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep4), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat4)
|
||||
|
||||
step4.text = "Metric system, high precision"
|
||||
let step3NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep3) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat3)
|
||||
step3NonOptional.text = "Metric system, low precision (nonOptional)"
|
||||
step3NonOptional.isOptional = false
|
||||
|
||||
let answerFormat4 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric, numericPrecision: ORKNumericPrecision.high, minimumValue: 20.0, maximumValue: 100.0, defaultValue: 45.50)
|
||||
|
||||
let step4 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep4), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat4)
|
||||
|
||||
step4.text = "Metric system, high precision"
|
||||
|
||||
let step4NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep4) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat4)
|
||||
step4NonOptional.text = "Metric system, high precision (nonOptional)"
|
||||
step4NonOptional.isOptional = false
|
||||
|
||||
let answerFormat5 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.USC)
|
||||
|
||||
let step5 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep5), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat5)
|
||||
|
||||
step5.text = "USC system, default precision"
|
||||
|
||||
let step5NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep5) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat5)
|
||||
step5NonOptional.text = "USC system, default precision (nonOptional)"
|
||||
step5NonOptional.isOptional = false
|
||||
|
||||
let answerFormat6 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.USC, numericPrecision: ORKNumericPrecision.high, minimumValue: 50.0, maximumValue: 150.0, defaultValue: 100.0)
|
||||
|
||||
let step6 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep6), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat6)
|
||||
|
||||
step6.text = "USC system, high precision"
|
||||
let step4NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep4) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat4)
|
||||
step4NonOptional.text = "Metric system, high precision (nonOptional)"
|
||||
step4NonOptional.isOptional = false
|
||||
|
||||
let answerFormat5 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.USC)
|
||||
|
||||
let step5 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep5), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat5)
|
||||
|
||||
step5.text = "USC system, default precision"
|
||||
|
||||
let step5NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep5) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat5)
|
||||
step5NonOptional.text = "USC system, default precision (nonOptional)"
|
||||
step5NonOptional.isOptional = false
|
||||
|
||||
let answerFormat6 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.USC, numericPrecision: ORKNumericPrecision.high, minimumValue: 50.0, maximumValue: 150.0, defaultValue: 100.0)
|
||||
|
||||
let step6 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep6), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat6)
|
||||
|
||||
step6.text = "USC system, high precision"
|
||||
|
||||
let step6NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep6) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat6)
|
||||
step6NonOptional.text = "USC system, high precision (nonOptional)"
|
||||
step6NonOptional.isOptional = false
|
||||
let step6NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep6) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat6)
|
||||
step6NonOptional.text = "USC system, high precision (nonOptional)"
|
||||
step6NonOptional.isOptional = false
|
||||
|
||||
let answerFormat7 = ORKHealthKitQuantityTypeAnswerFormat(quantityType: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!, unit: HKUnit.gramUnit(with: .kilo), style: .decimal)
|
||||
let step7 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep7), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat7)
|
||||
step7.text = "HealthKit, body mass"
|
||||
|
||||
let answerFormat7 = ORKHealthKitQuantityTypeAnswerFormat(quantityType: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!, unit: HKUnit.gramUnit(with: .kilo), style: .decimal)
|
||||
let step7NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep7) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat7)
|
||||
step7NonOptional.text = "HealthKit, body mass (nonOptional)"
|
||||
step7NonOptional.isOptional = false
|
||||
|
||||
let step7 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep7), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat7)
|
||||
|
||||
step7.text = "HealthKit, body mass"
|
||||
|
||||
let step7NonOptional = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep7) + "NonOptional", title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat7)
|
||||
step7NonOptional.text = "HealthKit, body mass (nonOptional)"
|
||||
step7NonOptional.isOptional = false
|
||||
|
||||
return ORKOrderedTask(identifier: String(describing: Identifier.weightQuestionTask), steps: [step1, step1NonOptional, step2, step2NonOptional, step3, step3NonOptional, step4, step4NonOptional, step5, step5NonOptional, step6, step6NonOptional, step7NonOptional, step7])
|
||||
return ORKOrderedTask(identifier: String(describing: Identifier.weightQuestionTask), steps: [step1, step1NonOptional, step2, step2NonOptional, step3, step3NonOptional, step4, step4NonOptional, step5, step5NonOptional, step6, step6NonOptional, step7NonOptional, step7])
|
||||
}
|
||||
|
||||
|
||||
private var healthQuantityTypeTask: ORKTask {
|
||||
let heartRateHealthKitQuantityTypeAnswerFormat = ORKHealthKitQuantityTypeAnswerFormat(quantityType: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!, unit: nil, style: .decimal)
|
||||
let heartRateQuestion = ORKQuestionStep(identifier: String(describing: Identifier.healthQuantityQuestion1), title: NSLocalizedString("Heart Rate", comment: ""), question: "What is your Heart Rate?", answer: heartRateHealthKitQuantityTypeAnswerFormat)
|
||||
@@ -1705,6 +1701,7 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
let notificationsPermissionType = ORKNotificationPermissionType(authorizationOptions: [.alert, .badge, .sound])
|
||||
|
||||
let motionActivityPermissionType = ORKMotionActivityPermissionType()
|
||||
let locationPermissionType = ORKLocationPermissionType()
|
||||
|
||||
let healthKitTypesToWrite: Set<HKSampleType> = [
|
||||
HKObjectType.quantityType(forIdentifier: .bodyMassIndex)!,
|
||||
@@ -1719,11 +1716,9 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
let healthKitPermissionType = ORKHealthKitPermissionType(sampleTypesToWrite: healthKitTypesToWrite,
|
||||
objectTypesToRead: healthKitTypesToRead)
|
||||
|
||||
let locationPermissionType = ORKLocationPermissionType()
|
||||
|
||||
let requestPermissionsStep = ORKRequestPermissionsStep(
|
||||
identifier: String(describing: Identifier.requestPermissionsStep),
|
||||
permissionTypes: [notificationsPermissionType, motionActivityPermissionType, healthKitPermissionType, locationPermissionType])
|
||||
identifier: String(describing: Identifier.requestPermissionsStep),
|
||||
permissionTypes: [notificationsPermissionType, motionActivityPermissionType, healthKitPermissionType, locationPermissionType])
|
||||
|
||||
requestPermissionsStep.title = "Health Data Request"
|
||||
requestPermissionsStep.text = "Please review the health data types below and enable sharing to contribute to the study."
|
||||
|
||||
Reference in New Issue
Block a user