Compare commits

..

4 Commits

Author SHA1 Message Date
Pariece McKinney 9b1153da04 Public release 2.2.16 2024-04-25 17:09:00 -04:00
Louie 38d161f1bf Stable Public Release 2.2.15
Merging main into stable
2023-12-05 14:20:25 -08:00
Louie 1b9daf60ee Merge pull request #1530 from ResearchKit/cocoapod_version_bump
Point ResearchKit.podspec to 2.1.0
2022-11-29 13:11:01 -08:00
Louis Chatta e71d71cf9c Point ResearchKit.podspec to 2.1.0 2022-11-29 11:48:27 -08:00
153 changed files with 1918 additions and 364 deletions
+92
View File
@@ -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>
+22
View File
@@ -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 dont use ResearchKits 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 apps 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 ResearchKits HealthKit features. Make sure to enable the HealthKit Entitlement
License<a name="license"></a>
=======
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'ResearchKit'
s.version = '2.1.0'
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/'
+65 -23
View File
@@ -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,10 +41,16 @@
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 */; };
0B6CD14529119CCC004BC4A0 /* ORKNormalizedReactionTimeViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAF979D291088F000EF138A /* ORKNormalizedReactionTimeViewController.h */; };
0B9CC5672A68C02C00080E29 /* UIImageView+ResearchKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B9CC5652A68C02C00080E29 /* UIImageView+ResearchKit.h */; };
0B9CC5682A68C02C00080E29 /* UIImageView+ResearchKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B9CC5662A68C02C00080E29 /* UIImageView+ResearchKit.m */; };
0BA0F4B22A1C1FD300A55672 /* ORKHealthKitQuestionStepViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BA0F4B12A1C1FD300A55672 /* ORKHealthKitQuestionStepViewControllerTests.swift */; };
0BAF97A0291088F200EF138A /* ORKNormalizedReactionTimeResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAF9796291088ED00EF138A /* ORKNormalizedReactionTimeResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
0BAF97A3291088F200EF138A /* ORKNormalizedReactionTimeStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAF9799291088EE00EF138A /* ORKNormalizedReactionTimeStep.h */; settings = {ATTRIBUTES = (Public, ); }; };
0BAF97A4291088F200EF138A /* ORKNormalizedReactionTimeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BAF979A291088EF00EF138A /* ORKNormalizedReactionTimeViewController.m */; };
@@ -52,6 +58,9 @@
0BAF97A6291088F200EF138A /* ORKNormalizedReactionTimeContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BAF979C291088F000EF138A /* ORKNormalizedReactionTimeContentView.m */; };
0BAF97A8291088F200EF138A /* ORKNormalizedReactionTimeResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BAF979E291088F100EF138A /* ORKNormalizedReactionTimeResult.m */; };
0BAF97A9291088F200EF138A /* ORKNormalizedReactionTimeStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BAF979F291088F200EF138A /* ORKNormalizedReactionTimeStep.m */; };
0BC8034F2B07F6B100618E4F /* ORKFormStepViewControllerORKTextChoiceOtherRestorationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC8034E2B07F6B100618E4F /* ORKFormStepViewControllerORKTextChoiceOtherRestorationTests.swift */; };
0BC8035E2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BC8035C2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h */; };
0BC8035F2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BC8035D2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.m */; };
106FF29E1B663FCE004EACF2 /* ORKHolePegTestPlaceStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 106FF29C1B663FCE004EACF2 /* ORKHolePegTestPlaceStep.h */; settings = {ATTRIBUTES = (Private, ); }; };
106FF29F1B663FCE004EACF2 /* ORKHolePegTestPlaceStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 106FF29D1B663FCE004EACF2 /* ORKHolePegTestPlaceStep.m */; };
106FF2A21B665B86004EACF2 /* ORKHolePegTestPlaceStepViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 106FF2A01B665B86004EACF2 /* ORKHolePegTestPlaceStepViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -193,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, ); }; };
@@ -219,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 */; };
@@ -754,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 */; };
@@ -1040,8 +1050,15 @@
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>"; };
0B9CC5652A68C02C00080E29 /* UIImageView+ResearchKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImageView+ResearchKit.h"; sourceTree = "<group>"; };
0B9CC5662A68C02C00080E29 /* UIImageView+ResearchKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+ResearchKit.m"; sourceTree = "<group>"; };
0BA0F4B12A1C1FD300A55672 /* ORKHealthKitQuestionStepViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORKHealthKitQuestionStepViewControllerTests.swift; sourceTree = "<group>"; };
0BAF9796291088ED00EF138A /* ORKNormalizedReactionTimeResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKNormalizedReactionTimeResult.h; sourceTree = "<group>"; };
0BAF9797291088EE00EF138A /* ORKNormalizedReactionTimeStimulusView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKNormalizedReactionTimeStimulusView.h; sourceTree = "<group>"; };
0BAF9798291088EE00EF138A /* ORKNormalizedReactionTimeContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKNormalizedReactionTimeContentView.h; sourceTree = "<group>"; };
@@ -1052,6 +1069,10 @@
0BAF979D291088F000EF138A /* ORKNormalizedReactionTimeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKNormalizedReactionTimeViewController.h; sourceTree = "<group>"; };
0BAF979E291088F100EF138A /* ORKNormalizedReactionTimeResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKNormalizedReactionTimeResult.m; sourceTree = "<group>"; };
0BAF979F291088F200EF138A /* ORKNormalizedReactionTimeStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKNormalizedReactionTimeStep.m; sourceTree = "<group>"; };
0BC8034D2B07F60600618E4F /* ORKFormStepViewController+TestingSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ORKFormStepViewController+TestingSupport.h"; sourceTree = "<group>"; };
0BC8034E2B07F6B100618E4F /* ORKFormStepViewControllerORKTextChoiceOtherRestorationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ORKFormStepViewControllerORKTextChoiceOtherRestorationTests.swift; sourceTree = "<group>"; };
0BC8035C2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h"; sourceTree = "<group>"; };
0BC8035D2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.m"; sourceTree = "<group>"; };
106FF29C1B663FCE004EACF2 /* ORKHolePegTestPlaceStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKHolePegTestPlaceStep.h; sourceTree = "<group>"; };
106FF29D1B663FCE004EACF2 /* ORKHolePegTestPlaceStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKHolePegTestPlaceStep.m; sourceTree = "<group>"; };
106FF2A01B665B86004EACF2 /* ORKHolePegTestPlaceStepViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKHolePegTestPlaceStepViewController.h; sourceTree = "<group>"; };
@@ -1194,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>"; };
@@ -1805,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>"; };
@@ -2065,7 +2087,6 @@
buildActionMask = 2147483647;
files = (
00B1F7852241503900D022FE /* Speech.framework in Frameworks */,
B1C7955E1A9FBF04007279BA /* HealthKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2083,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 = (
@@ -2361,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>";
@@ -2479,6 +2512,7 @@
3FFF18341829DB1D00167070 = {
isa = PBXGroup;
children = (
0B4D0F972BC87AB100DCB8B2 /* PrivacyInfo.xcprivacy */,
05F3765923C797930068E166 /* ResearchKit.xctestplan */,
168EEAAE230B6F9E003FD2FA /* scripts */,
B11DF3B21AA109C8009E76D2 /* docs */,
@@ -2502,7 +2536,6 @@
isa = PBXGroup;
children = (
00B1F7842241503900D022FE /* Speech.framework */,
B1C7955D1A9FBF04007279BA /* HealthKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -2858,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 = (
@@ -2884,6 +2902,7 @@
5D000EC12620F27100E5442A /* ResearchKit */ = {
isa = PBXGroup;
children = (
0B0EF9C62B8FB87600E2A97B /* ResearchKitTests */,
5D000EC22620F27100E5442A /* ResearchKit-Debug.xcconfig */,
5D000EC42620F27100E5442A /* ResearchKit-Shared.xcconfig */,
511A78992950D7030011D85D /* ResearchKit-Release.xcconfig */,
@@ -3028,7 +3047,6 @@
B1C1DE4F196F541F00F75544 /* ResearchKit.h */,
BC94EF2F1E962F7400143081 /* ORKDeprecated.h */,
BC94EF301E962F7400143081 /* ORKDeprecated.m */,
51EAFC10289B116300CFA3EB /* Configuration */,
86C40B511A8D7C5B00081FAC /* Common */,
86C40AF91A8D7C5B00081FAC /* Active Tasks */,
259E76FB1AFFAEAC0070F786 /* Charts */,
@@ -3121,6 +3139,8 @@
86CC8EA71AC09383001CCD89 /* Info.plist */,
86CC8EA81AC09383001CCD89 /* ORKAccessibilityTests.m */,
248604051B4C98760010C8A0 /* ORKAnswerFormatTests.m */,
0B7D32E92AE6F8040071C576 /* ORKQuestionStepViewController+TestingSupport.h */,
0BC8034D2B07F60600618E4F /* ORKFormStepViewController+TestingSupport.h */,
0B59A6BD28C1738D005035B4 /* ORKPickerTestDelegate.h */,
0B59A6BE28C1738D005035B4 /* ORKPickerTestDelegate.m */,
86CC8EA91AC09383001CCD89 /* ORKChoiceAnswerFormatHelperTests.m */,
@@ -3142,6 +3162,8 @@
1490DD01224D6A21003FEEDA /* ORKResultPredicateTests.swift */,
1490DD03224D6A61003FEEDA /* ORKTestResultPredicateType.swift */,
14F7AC8A2269035200D52F41 /* ORKStepViewControllerTests.swift */,
0BC8034E2B07F6B100618E4F /* ORKFormStepViewControllerORKTextChoiceOtherRestorationTests.swift */,
0BA0F4B12A1C1FD300A55672 /* ORKHealthKitQuestionStepViewControllerTests.swift */,
14E7903F226A5F72009D8083 /* ORKStepViewControllerHelpers.swift */,
);
path = ResearchKitTests;
@@ -3297,6 +3319,8 @@
86C40BEA1A8D7C5C00081FAC /* UIResponder+ResearchKit.m */,
805685771C90C19500BF437A /* UIImage+ResearchKit.h */,
805685781C90C19500BF437A /* UIImage+ResearchKit.m */,
0B9CC5652A68C02C00080E29 /* UIImageView+ResearchKit.h */,
0B9CC5662A68C02C00080E29 /* UIImageView+ResearchKit.m */,
);
name = UIKitCategories;
sourceTree = "<group>";
@@ -3456,6 +3480,8 @@
86C40B651A8D7C5B00081FAC /* ORKAnswerFormat.m */,
86C40B661A8D7C5B00081FAC /* ORKAnswerFormat_Internal.h */,
244EFAD11BCEFD83001850D9 /* ORKAnswerFormat_Private.h */,
0BC8035C2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h */,
0BC8035D2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.m */,
86C40B8A1A8D7C5C00081FAC /* ORKHealthAnswerFormat.h */,
86C40B8B1A8D7C5C00081FAC /* ORKHealthAnswerFormat.m */,
BABBB19B2093299A00CB29E5 /* ORKSurveyCardHeaderView.h */,
@@ -4290,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 */,
@@ -4551,6 +4578,7 @@
86C40CEE1A8D7C5C00081FAC /* ORKAnswerTextView.h in Headers */,
FF919A271E81A87B005C2A1E /* ORKActiveTaskResult.h in Headers */,
86C40C421A8D7C5C00081FAC /* ORKSpatialSpanMemoryStep.h in Headers */,
0BC8035E2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h in Headers */,
86C40C6E1A8D7C5C00081FAC /* CMMotionActivity+ORKJSONDictionary.h in Headers */,
B11C54991A9EEF8800265E61 /* ORKConsentSharingStep.h in Headers */,
805685791C90C19500BF437A /* UIImage+ResearchKit.h in Headers */,
@@ -4580,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 */,
@@ -4639,7 +4668,7 @@
861D2AF01B8409D9008C4CD0 /* ORKTimedWalkContentView.h in Headers */,
2489F7B31D65214D008DEF20 /* ORKVideoCaptureStepViewController.h in Headers */,
86C40E0C1A8D7C5C00081FAC /* ORKConsentReviewStepViewController.h in Headers */,
511B8AAE293A767C00049947 /* ORKTouchAbilityTouchTracker.h in Headers */,
0B9CC5672A68C02C00080E29 /* UIImageView+ResearchKit.h in Headers */,
86C40C321A8D7C5C00081FAC /* ORKFitnessStepViewController.h in Headers */,
FF5CA6121D2C2670001660A3 /* ORKTableStep.h in Headers */,
BCC1CD9A1B7ED64F00D86886 /* ORKYAxisView.h in Headers */,
@@ -4872,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;
@@ -4898,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 */,
@@ -4983,6 +5015,7 @@
14F7AC8B2269035200D52F41 /* ORKStepViewControllerTests.swift in Sources */,
BAB96755226E5D67006AAC56 /* ORKStepContainerViewTests.m in Sources */,
14BE7092220A206B005DEF07 /* ORKDataLoggerManagerTests.m in Sources */,
0BA0F4B22A1C1FD300A55672 /* ORKHealthKitQuestionStepViewControllerTests.swift in Sources */,
14D3F09C225BCA8100A3962D /* ORKBorderedButtonTests.swift in Sources */,
1483DBB5220125BE004C26B6 /* ORKActiveStepTests.swift in Sources */,
1490DCF6224D426B003FEEDA /* ORKSignatureResultTests.swift in Sources */,
@@ -5009,6 +5042,7 @@
14BE7091220A201E005DEF07 /* ORKDataLoggerTests.m in Sources */,
148E58BD227B36DB00EEF915 /* ORKCompletionStepViewControllerTests.swift in Sources */,
86CC8EB31AC09383001CCD89 /* ORKAccessibilityTests.m in Sources */,
0BC8034F2B07F6B100618E4F /* ORKFormStepViewControllerORKTextChoiceOtherRestorationTests.swift in Sources */,
1490DD02224D6A21003FEEDA /* ORKResultPredicateTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -5074,6 +5108,7 @@
86C40CDA1A8D7C5C00081FAC /* ORKTextFieldView.m in Sources */,
8419D6731FB73EC60088D7E5 /* ORKWebViewStepViewController.m in Sources */,
517514572459F0BE009E8FFC /* ORK3DModelStepContentView.m in Sources */,
0B9CC5682A68C02C00080E29 /* UIImageView+ResearchKit.m in Sources */,
B8760F2C1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.m in Sources */,
86C40D821A8D7C5C00081FAC /* ORKSelectionSubTitleLabel.m in Sources */,
FF919A441E81B904005C2A1E /* ORKPSATResult.m in Sources */,
@@ -5176,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 */,
@@ -5398,6 +5434,7 @@
BCD192EC1B81245500FCC08A /* ORKPieChartTitleTextView.m in Sources */,
2489F7B41D65214D008DEF20 /* ORKVideoCaptureStepViewController.m in Sources */,
861D2AF71B843968008C4CD0 /* ORKCompletionStepViewController.m in Sources */,
0BC8035F2B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.m in Sources */,
BCB6E65F1B7D534C000D5B34 /* ORKGraphChartView.m in Sources */,
24BC5CEF1BC345D900846B43 /* ORKLoginStep.m in Sources */,
511B8A92293A757E00049947 /* ORKTouchAbilityContentView.m in Sources */,
@@ -5533,6 +5570,7 @@
};
86CC8EA41AC09332001CCD89 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0B0EF9C82B8FB87600E2A97B /* ResearchKitTests-Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ADDRESS_SANITIZER_CONTAINER_OVERFLOW = YES;
@@ -5541,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
-1
View File
@@ -30,7 +30,6 @@
@import UIKit;
@import HealthKit;
#import <ResearchKit/ORKStep.h>
+2
View File
@@ -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];
@@ -45,6 +45,9 @@
#import "ORKTaskViewController_Internal.h"
#import "ORKRecorder_Internal.h"
#import "ORKStepView_Private.h"
#import "ORKStepContentView.h"
#import "ORKActiveStep_Internal.h"
#import "ORKCollectionResult_Private.h"
#import "ORKResult.h"
@@ -125,6 +128,7 @@
if (_customView) {
_activeStepView.customContentView = _customView;
}
_activeStepView.stepContentView.shouldAutomaticallyAdjustImageTintColor = YES;
[self.view addSubview:_activeStepView];
}
@@ -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
+15 -13
View File
@@ -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
+9 -2
View File
@@ -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.
+3
View File
@@ -89,9 +89,12 @@
return nil;
}
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
- (NSSet<HKObjectType *> *)requestedHealthKitTypesForReading {
return nil;
}
#endif
- (ORKPermissionMask)requestedPermissionMask {
return ORKPermissionNone;
}
@@ -51,7 +51,6 @@
- (void)validateParameters {
[super validateParameters];
// TODO:
}
- (BOOL)startsFinished {
@@ -49,7 +49,6 @@
- (void)validateParameters {
[super validateParameters];
// TODO:
}
- (BOOL)startsFinished {
@@ -49,7 +49,6 @@
- (void)validateParameters {
[super validateParameters];
// TODO:
}
- (BOOL)startsFinished {
@@ -50,7 +50,6 @@
- (void)validateParameters {
[super validateParameters];
// TODO:
}
- (BOOL)startsFinished {
@@ -51,7 +51,6 @@
- (void)validateParameters {
[super validateParameters];
// TODO:
}
- (BOOL)startsFinished {
@@ -51,7 +51,6 @@
- (void)validateParameters {
[super validateParameters];
// TODO:
}
- (BOOL)startsFinished {
@@ -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
+17 -2
View File
@@ -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;
+19 -5
View File
@@ -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
+1 -1
View File
@@ -30,10 +30,10 @@
@import UIKit;
#import "ORKDefaultFont.h"
#import "ORKDefines.h"
NS_ASSUME_NONNULL_BEGIN
/**
+7 -2
View File
@@ -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.
+2 -2
View File
@@ -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
+2 -1
View File
@@ -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.
+12 -3
View File
@@ -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;
+2 -1
View File
@@ -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
+36 -8
View File
@@ -57,9 +57,11 @@
#import "ORKFormStep_Internal.h"
#import "ORKResult_Private.h"
#import "ORKStep_Private.h"
#import "ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h"
#import "ORKSESSelectionView.h"
#import "ORKHelpers_Internal.h"
#import "ORKAnswerTextView.h"
#import "ORKSkin.h"
static const CGFloat TableViewYOffsetStandard = 30.0;
@@ -333,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");
@@ -375,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];
@@ -402,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;
@@ -468,7 +474,29 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
[self notifyDelegateOnResultChange];
}
- (void)restoreTextChoiceOtherCellStateWithSavedAnswer:(NSArray *)savedAnswer formItem:(ORKFormItem *)formItem choiceOtherViewCell:(ORKChoiceOtherViewCell *)choiceOtherViewCell {
id savedAnswerValue = ORKDynamicCast(savedAnswer, NSArray).firstObject;
if (savedAnswerValue != nil) {
ORKTextChoiceAnswerFormat *textChoiceAnswerFormat = ORKDynamicCast(formItem.impliedAnswerFormat, ORKTextChoiceAnswerFormat);
NSString *textChoiceAnswer = ORKDynamicCast(savedAnswerValue, NSString);
if (textChoiceAnswer && [textChoiceAnswerFormat hasStandardTextChoiceOtherArrangement]) {
ORKTextChoiceOther *textChoiceOther = ORKDynamicCast(formItem.impliedAnswerFormat.choices.lastObject, ORKTextChoiceOther);
// You can use ORKTextChoice and ORKTextChoiceOther as the choices of the ORKTextChoiceAnswerFormat.
// However, ResearchKit only supports restoring the ORKTextChoiceOther if it is the last choice.
if (textChoiceOther) {
[choiceOtherViewCell setCellSelected:YES highlight:NO];
textChoiceOther.textViewText = textChoiceAnswer;
choiceOtherViewCell.textViewHidden = NO;
choiceOtherViewCell.textView.text = textChoiceOther.textViewText;
}
}
}
}
- (void)refreshDefaults {
// defaults only come from HealthKit
NSArray *formItems = [self formItems];
ORKAnswerDefaultSource *source = _defaultSource;
ORKWeakTypeOf(self) weakSelf = self;
@@ -494,10 +522,7 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
ORKStrongTypeOf(weakSelf) strongSelf = weakSelf;
[strongSelf updateDefaults:defaults];
});
});
});
}
- (void)removeAnswerForIdentifier:(NSString *)identifier {
@@ -1154,9 +1179,10 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
section.textChoiceCellGroup.delegate = self;
ORKChoiceViewCell *choiceViewCell = nil;
choiceViewCell = [section.textChoiceCellGroup cellAtIndexPath:indexPath withReuseIdentifier:identifier];
if ([choiceViewCell isKindOfClass:[ORKChoiceOtherViewCell class]]) {
ORKChoiceOtherViewCell *choiceOtherViewCell = (ORKChoiceOtherViewCell *)choiceViewCell;
ORKChoiceOtherViewCell *choiceOtherViewCell = ORKDynamicCast(choiceViewCell, ORKChoiceOtherViewCell);
if (choiceOtherViewCell) {
choiceOtherViewCell.delegate = self;
[self restoreTextChoiceOtherCellStateWithSavedAnswer:answer formItem:formItem choiceOtherViewCell:choiceOtherViewCell];
}
choiceViewCell.tintColor = ORKViewTintColor(self.view);
choiceViewCell.useCardView = [self formStep].useCardView;
@@ -1571,7 +1597,9 @@ static NSString *const _ORKAnsweredSectionsRestoreKey = @"answeredSections";
if (_currentFirstResponderCell == choiceOtherViewCell) {
_currentFirstResponderCell = nil;
}
NSIndexPath *indexPath = [_tableView indexPathForCell:choiceOtherViewCell];
// we need to use `indexPathForRowAtPoint` because `indexPathForCell`
// will return nil if the cell is off the screen, which will happen if we are scrolling
NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:choiceOtherViewCell.center];
ORKTableSection *section = _sections[indexPath.section];
[section.textChoiceCellGroup textViewDidResignResponderForCellAtIndexPath:indexPath];
}
+7 -2
View File
@@ -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
+2 -1
View File
@@ -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
+2 -1
View File
@@ -173,7 +173,8 @@ static const CGFloat PickerMinimumHeight = 34.0;
- (void)pickerWillAppear {
// Report current value, since ORKHeightPicker always has a value
[self pickerView];
[self valueDidChange:self];
// only do the assignment that's done in `valueDidChange`
_answer = [self selectedAnswerValue];
[self accessibilityFocusOnPickerElement];
}
+63 -10
View File
@@ -37,7 +37,8 @@
#import "ORKHelpers_Internal.h"
#import "ORKSkin.h"
#import "UIImageView+ResearchKit.h"
#import "UIImage+ResearchKit.h"
@interface ORKChoiceButtonView : UIView
@@ -45,6 +46,7 @@
@property (nonatomic, strong) UIButton *button;
@property (nonatomic, copy) NSString *labelText;
@property (nonatomic, copy) ORKImageChoice *choice;
@end
@@ -54,17 +56,12 @@
- (instancetype)initWithImageChoice:(ORKImageChoice *)choice {
self = [super init];
if (self) {
_choice = [choice copy];
_labelText = choice.text.length > 0 ? choice.text: @" ";
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
_button.exclusiveTouch = YES;
if (choice.selectedStateImage) {
[_button setImage:choice.selectedStateImage forState:UIControlStateSelected];
}
[_button setImage:choice.normalStateImage forState:UIControlStateNormal];
[self setupButtonImagesFromImageChoice:choice];
_button.imageView.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:_button];
@@ -78,10 +75,46 @@
} else {
self.button.accessibilityLabel = self.labelText;
}
[self updateViewColors];
}
return self;
}
- (void)setupButtonImagesFromImageChoice:(ORKImageChoice *)choice {
if ([UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark) {
[_button setImage:[_button.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
} else {
[_button setImage:[_button.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forState:UIControlStateNormal];
}
if (choice.selectedStateImage) {
UIImage *selectedStateImage = choice.selectedStateImage;
if (@available(iOS 12.0, *)) {
selectedStateImage = [choice.selectedStateImage ork_imageWithRenderingModeForUserInterfaceStyle:self.traitCollection.userInterfaceStyle];
}
[_button setImage:selectedStateImage forState:UIControlStateSelected];
}
UIImage *normalStateImage = choice.normalStateImage;
if (@available(iOS 12.0, *)) {
normalStateImage = [choice.normalStateImage ork_imageWithRenderingModeForUserInterfaceStyle:self.traitCollection.userInterfaceStyle];
}
[_button setImage:normalStateImage forState:UIControlStateNormal];
}
- (void)updateViewColors {
if (@available(iOS 12.0, *)) {
[_button.imageView updateRenderingModeForUserInterfaceStyle:self.traitCollection.userInterfaceStyle];
_button.imageView.tintColor = self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ? [UIColor whiteColor] : nil;
}
}
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
[self setupButtonImagesFromImageChoice:_choice];
}
- (void)setUpConstraints {
NSMutableArray *constraints = [NSMutableArray new];
@@ -188,6 +221,7 @@ static const CGFloat SpacerHeight = 5.0;
ORKChoiceButtonView *buttonView = [[ORKChoiceButtonView alloc] initWithImageChoice:imageChoice];
[buttonView.button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
buttonView.button.imageView.layer.cornerRadius = ORKImageChoiceButtonCornerRadii;
[buttonViews addObject:buttonView];
[self addSubview:buttonView];
}
@@ -370,7 +404,16 @@ static const CGFloat SpacerHeight = 5.0;
- (void)resetLabelText {
_placeHolderLabel.hidden = NO;
_choiceLabel.hidden = !_placeHolderLabel.hidden;
}
- (void)resetButtonSelection:(UIButton *)button {
[_buttonViews enumerateObjectsUsingBlock:^(ORKChoiceButtonView *buttonView, NSUInteger idx, BOOL *stop) {
if (_singleChoice) {
buttonView.button.imageView.backgroundColor = nil;
} else if ([buttonView.button isEqual: button]) {
buttonView.button.imageView.backgroundColor = nil;
}
}];
}
- (void)setLabelText:(NSString *)text {
@@ -398,6 +441,7 @@ static const CGFloat SpacerHeight = 5.0;
if (buttonView.button != button) {
if (_singleChoice) {
buttonView.button.selected = NO;
buttonView.button.imageView.backgroundColor = nil;
}
} else {
if (_singleChoice) {
@@ -405,6 +449,7 @@ static const CGFloat SpacerHeight = 5.0;
} else {
[self setLabelText:[_helper labelForChoiceAnswer:[_helper answerForSelectedIndexes:[self selectedIndexes]]]];
}
buttonView.button.imageView.backgroundColor = [UIColor lightGrayColor];
}
}];
@@ -415,6 +460,7 @@ static const CGFloat SpacerHeight = 5.0;
} else {
[self setLabelText:[_helper labelForChoiceAnswer:[_helper answerForSelectedIndexes:[self selectedIndexes]]]];
}
[self resetButtonSelection:button];
}
_answer = [_helper answerForSelectedIndexes:[self selectedIndexes]];
@@ -447,9 +493,16 @@ static const CGFloat SpacerHeight = 5.0;
if (number.unsignedIntegerValue < _buttonViews.count) {
ORKChoiceButtonView *buttonView = _buttonViews[number.unsignedIntegerValue];
[buttonView button].selected = YES;
[self setLabelText:buttonView.labelText];
buttonView.button.imageView.backgroundColor = [UIColor lightGrayColor];
if (_singleChoice) {
[self setLabelText:buttonView.labelText];
}
}
}];
if (!_singleChoice) {
[self setLabelText:[_helper labelForChoiceAnswer:[_helper answerForSelectedIndexes:[self selectedIndexes]]]];
}
}
- (BOOL)isAccessibilityElement {
@@ -71,6 +71,7 @@
if (self.step && [self isViewLoaded]) {
self.stepView = [[ORKInstructionStepContainerView alloc] initWithInstructionStep:[self instructionStep]];
_stepView.delegate = self;
_stepView.stepContentView.shouldAutomaticallyAdjustImageTintColor = [self instructionStep].shouldAutomaticallyAdjustImageTintColor;
_stepView.stepContentView.bodyContainerView.bodyItemDelegate = self;
[self.view addSubview:self.stepView];
[self setNavigationFooterView];
@@ -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
@@ -162,10 +162,8 @@ static const CGFloat detailTextBottomSpacing = 16.0;
}
- (void)didMoveToWindow {
_appTintColor = ORKViewTintColor(self);
_continueButton.normalTintColor = _appTintColor;
_skipButton.normalTintColor = _appTintColor;
[self udpateTintColor];
[super didMoveToWindow];
}
- (void)setSkipButtonStyle:(ORKNavigationContainerButtonStyle)skipButtonStyle {
@@ -559,8 +557,15 @@ static const CGFloat detailTextBottomSpacing = 16.0;
}
- (void)tintColorDidChange {
[self udpateTintColor];
[super tintColorDidChange];
[self didMoveToWindow];
}
- (void)udpateTintColor {
_appTintColor = ORKViewTintColor(self);
_continueButton.normalTintColor = _appTintColor;
_skipButton.normalTintColor = _appTintColor;
}
@end
@@ -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];
}
@@ -181,6 +184,7 @@ void ORKStepArrayAddStep(NSMutableArray *array, ORKStep *step) {
step.title = ORKLocalizedString(@"TASK_COMPLETE_TITLE", nil);
step.text = ORKLocalizedString(@"TASK_COMPLETE_TEXT", nil);
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
return step;
}
@@ -227,6 +231,7 @@ NSString *const ORKAmslerGridCalibrationRightIdentifier = @"amsler.grid.calibrat
step.image = [UIImage imageNamed:@"amslerGrid" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
{
@@ -243,6 +248,7 @@ NSString *const ORKAmslerGridCalibrationRightIdentifier = @"amsler.grid.calibrat
step.image = [UIImage imageNamed:@"amslerGrid" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -263,7 +269,8 @@ NSString *const ORKAmslerGridCalibrationRightIdentifier = @"amsler.grid.calibrat
step.image = [UIImage imageNamed:@"amslerGrid" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -311,7 +318,8 @@ NSString *const ORKHolePegTestNonDominantRemoveStepIdentifier = @"hole.peg.test.
step.image = [UIImage imageNamed:@"phoneholepeg" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -329,7 +337,8 @@ NSString *const ORKHolePegTestNonDominantRemoveStepIdentifier = @"hole.peg.test.
step.image = [UIImage animatedImageWithImages:@[image1, image2, image3, image4, image5, image6] duration:4];
step.imageContentMode = UIViewContentModeScaleAspectFit;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -446,6 +455,7 @@ NSString *const ORKTappingStepIdentifier = @"tapping";
step.image = [UIImage imageNamed:imageName inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeScaleAspectFit;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -531,7 +541,8 @@ NSString *const ORKTappingStepIdentifier = @"tapping";
}
step.imageContentMode = UIViewContentModeScaleAspectFit;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -612,6 +623,7 @@ NSString *const ORKAudioTooLoudStepIdentifier = @"audio.tooloud";
step.image = [UIImage imageNamed:@"phonewaves" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -623,6 +635,7 @@ NSString *const ORKAudioTooLoudStepIdentifier = @"audio.tooloud";
step.image = [UIImage imageNamed:@"phonewaves" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -649,7 +662,8 @@ NSString *const ORKAudioTooLoudStepIdentifier = @"audio.tooloud";
step.title = ORKLocalizedString(@"AUDIO_TASK_TITLE", nil);
step.text = ORKLocalizedString(@"AUDIO_TOO_LOUD_MESSAGE", nil);
step.detailText = ORKLocalizedString(@"AUDIO_TOO_LOUD_ACTION_NEXT", nil);
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -709,6 +723,7 @@ NSString *const ORKFitnessRestStepIdentifier = @"fitness.rest";
step.image = [UIImage imageNamed:@"heartbeat" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -719,6 +734,7 @@ NSString *const ORKFitnessRestStepIdentifier = @"fitness.rest";
step.image = [UIImage imageNamed:@"walkingman" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -801,6 +817,7 @@ NSString *const ORKSixMinuteWalkFatigueIdentifier = @"6mwt.fatigue";
// Explanation Step
ORKInstructionStep *explainStep = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier];
explainStep.iconImage = [UIImage systemImageNamed:@"figure.walk"];
explainStep.shouldAutomaticallyAdjustImageTintColor = YES;
explainStep.title = ORKLocalizedString(@"6MWT_TASK_TITLE", nil);
explainStep.text = intendedUseDescription ? : ORKLocalizedString(@"6MWT_INTRO", nil);
explainStep.bodyItems = @[
@@ -963,6 +980,7 @@ NSString *const ORKShortWalkRestStepIdentifier = @"walking.rest";
step.detailText = ORKLocalizedString(@"WALK_INTRO_TEXT", nil);
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -974,6 +992,7 @@ NSString *const ORKShortWalkRestStepIdentifier = @"walking.rest";
step.image = [UIImage imageNamed:@"pocket" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -1108,6 +1127,7 @@ NSString *const ORKShortWalkRestStepIdentifier = @"walking.rest";
step.detailText = ORKLocalizedString(@"WALK_INTRO_TEXT", nil);
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1119,6 +1139,7 @@ NSString *const ORKShortWalkRestStepIdentifier = @"walking.rest";
step.image = [UIImage imageNamed:@"pocket" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -1232,6 +1253,7 @@ NSString *const ORKKneeRangeOfMotionStepIdentifier = @"knee.range.of.motion";
if (@available(iOS 13.0, *)) {
// Use body items with SFSymbols in iOS 13+
ORKInstructionStep *instructionStep = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier];
instructionStep.shouldAutomaticallyAdjustImageTintColor = YES;
instructionStep.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil);
instructionStep.text = intendedUseDescription;
@@ -1289,17 +1311,22 @@ NSString *const ORKKneeRangeOfMotionStepIdentifier = @"knee.range.of.motion";
instructionStep0.detailText = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT", nil);
instructionStep0.shouldTintImages = YES;
instructionStep0.imageContentMode = UIViewContentModeCenter;
instructionStep0.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, instructionStep0);
ORKInstructionStep *instructionStep1 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier];
instructionStep1.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil);
instructionStep1.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT", nil);
instructionStep1.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, instructionStep1);
ORKInstructionStep *instructionStep2 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier];
instructionStep2.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil);
instructionStep2.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TITLE_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TITLE_RIGHT", nil);
instructionStep2.shouldAutomaticallyAdjustImageTintColor = YES;
instructionStep2.detailText = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT", nil);
instructionStep2.image = kneeStartImage;
instructionStep2.imageContentMode = UIViewContentModeCenter;
@@ -1309,6 +1336,7 @@ NSString *const ORKKneeRangeOfMotionStepIdentifier = @"knee.range.of.motion";
ORKInstructionStep *instructionStep3 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction3StepIdentifier];
instructionStep3.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil);
instructionStep3.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT", nil);
instructionStep3.shouldAutomaticallyAdjustImageTintColor = YES;
instructionStep3.image = kneeMaximumImage;
instructionStep3.imageContentMode = UIViewContentModeCenter;
@@ -1376,12 +1404,14 @@ NSString *const ORKShoulderRangeOfMotionStepIdentifier = @"shoulder.range.of.mot
instructionStep0.text = intendedUseDescription;
instructionStep0.detailText = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT", nil) : ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT", nil);
instructionStep0.shouldTintImages = YES;
instructionStep0.shouldAutomaticallyAdjustImageTintColor = YES;
instructionStep0.imageContentMode = UIViewContentModeCenter;
ORKStepArrayAddStep(steps, instructionStep0);
ORKInstructionStep *instructionStep1 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier];
instructionStep1.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil);
instructionStep1.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT", nil) : ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT", nil);
instructionStep1.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, instructionStep1);
ORKInstructionStep *instructionStep2 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier];
@@ -1390,6 +1420,7 @@ NSString *const ORKShoulderRangeOfMotionStepIdentifier = @"shoulder.range.of.mot
instructionStep2.image = shoulderStartImage;
instructionStep2.imageContentMode = UIViewContentModeCenter;
instructionStep2.shouldTintImages = YES;
instructionStep2.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, instructionStep2);
ORKInstructionStep *instructionStep3 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction3StepIdentifier];
@@ -1398,6 +1429,7 @@ NSString *const ORKShoulderRangeOfMotionStepIdentifier = @"shoulder.range.of.mot
instructionStep3.image = shoulderMaximumImage;
instructionStep3.imageContentMode = UIViewContentModeCenter;
instructionStep3.shouldTintImages = YES;
instructionStep3.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, instructionStep3);
}
@@ -1463,7 +1495,8 @@ NSString *const ORKSpatialSpanMemoryStepIdentifier = @"cognitive.memory.spatials
step.image = [UIImage imageNamed:@"memory" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeScaleAspectFit;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1480,7 +1513,8 @@ NSString *const ORKSpatialSpanMemoryStepIdentifier = @"cognitive.memory.spatials
}
step.imageContentMode = UIViewContentModeScaleAspectFit;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -1536,7 +1570,8 @@ NSString *const ORKSpeechRecognitionStepIdentifier = @"speech.recognition";
step.image = [UIImage imageNamed:@"phonewaves" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.shouldTintImages = YES;
step.imageContentMode = UIViewContentModeCenter;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1548,7 +1583,8 @@ NSString *const ORKSpeechRecognitionStepIdentifier = @"speech.recognition";
step.image = [UIImage imageNamed:@"phonewavesspeech" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -1605,7 +1641,8 @@ NSString *const ORKSpeechInNoiseStep2Identifier = @"speech.in.noise2";
step.image = [UIImage imageNamed:@"speechInNoise" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
{
@@ -1615,7 +1652,8 @@ NSString *const ORKSpeechInNoiseStep2Identifier = @"speech.in.noise2";
step.image = [UIImage imageNamed:@"speechInNoise" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1694,7 +1732,8 @@ NSString *const ORKStroopStepIdentifier = @"stroop";
step.image = [UIImage imageNamed:@"phonestrooplabel" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
{
@@ -1704,7 +1743,8 @@ NSString *const ORKStroopStepIdentifier = @"stroop";
step.image = [UIImage imageNamed:@"phonestroopbutton" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -1762,6 +1802,7 @@ NSString *const ORKToneAudiometryStepIdentifier = @"tone.audiometry";
step.image = [UIImage imageNamed:@"phonewaves_inverted" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1774,6 +1815,7 @@ NSString *const ORKToneAudiometryStepIdentifier = @"tone.audiometry";
step.image = [UIImage imageNamed:@"phonefrequencywaves" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1846,6 +1888,7 @@ NSString *const ORKdBHLToneAudiometryStep2Identifier = @"dBHL2.tone.audiometry";
step.image = [UIImage imageNamed:@"audiometry" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
if (@available(iOS 13.0, *)) {
ORKBodyItem * item1 = [[ORKBodyItem alloc] initWithText:ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1", nil) detailText:nil image:[UIImage systemImageNamed:@"ear"] learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleImage];
ORKBodyItem * item2 = [[ORKBodyItem alloc] initWithText:ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2", nil) detailText:nil image:[UIImage systemImageNamed:@"hand.draw.fill"] learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleImage];
@@ -1876,7 +1919,8 @@ NSString *const ORKdBHLToneAudiometryStep2Identifier = @"dBHL2.tone.audiometry";
step.image = [UIImage imageNamed:@"audiometry" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1893,7 +1937,9 @@ NSString *const ORKdBHLToneAudiometryStep2Identifier = @"dBHL2.tone.audiometry";
{
ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier];
step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR", nil);
step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR", nil);
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1910,6 +1956,7 @@ NSString *const ORKdBHLToneAudiometryStep2Identifier = @"dBHL2.tone.audiometry";
ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction3StepIdentifier];
step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR", nil);
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1932,7 +1979,6 @@ NSString *const ORKdBHLToneAudiometryStep2Identifier = @"dBHL2.tone.audiometry";
return task;
}
#pragma mark - towerOfHanoiTask
NSString *const ORKTowerOfHanoiStepIdentifier = @"towerOfHanoi";
@@ -1953,7 +1999,8 @@ NSString *const ORKTowerOfHanoiStepIdentifier = @"towerOfHanoi";
step.image = [UIImage imageNamed:@"phone-tower-of-hanoi" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -1965,7 +2012,8 @@ NSString *const ORKTowerOfHanoiStepIdentifier = @"towerOfHanoi";
step.image = [UIImage imageNamed:@"tower-of-hanoi-second-screen" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -2014,7 +2062,8 @@ NSString *const ORKReactionTimeStepIdentifier = @"reactionTime";
step.image = [UIImage imageNamed:@"phoneshake" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2026,7 +2075,8 @@ NSString *const ORKReactionTimeStepIdentifier = @"reactionTime";
step.image = [UIImage imageNamed:@"phoneshakecircle" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -2082,7 +2132,8 @@ NSString *const ORKNormalizedReactionTimeStepIdentifier = @"normalizedReactionTi
step.image = [UIImage imageNamed:@"phoneshake" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2094,7 +2145,8 @@ NSString *const ORKNormalizedReactionTimeStepIdentifier = @"normalizedReactionTi
step.image = [UIImage imageNamed:@"phoneshakecircle" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -2154,6 +2206,7 @@ NSString *const ORKTimedWalkTrial2StepIdentifier = @"timed.walk.trial2";
step.text = intendedUseDescription;
step.detailText = ORKLocalizedString(@"TIMED_WALK_INTRO_DETAIL", nil);
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2201,6 +2254,7 @@ NSString *const ORKTimedWalkTrial2StepIdentifier = @"timed.walk.trial2";
step.image = [UIImage imageNamed:@"timer" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2326,7 +2380,8 @@ NSString *const ORKPSATStepIdentifier = @"psat";
step.image = [UIImage imageNamed:@"psatDice" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
{
@@ -2342,7 +2397,8 @@ NSString *const ORKPSATStepIdentifier = @"psat";
NSString *seconds = [secondsFormatter stringFromTimeInterval:interStimulusInterval];
step.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"PSAT_INTRO_TEXT_2_%@", nil), seconds];
step.detailText = ORKLocalizedString(@"PSAT_CALL_TO_ACTION", nil);
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -2425,7 +2481,8 @@ NSString *const ORKTremorTestTurnWristStepIdentifier = @"tremor.handQueenWave";
step.imageContentMode = UIViewContentModeScaleAspectFit;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2448,7 +2505,8 @@ NSString *const ORKTremorTestTurnWristStepIdentifier = @"tremor.handQueenWave";
step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT", nil);
}
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2499,7 +2557,8 @@ NSString *const ORKTremorTestTurnWristStepIdentifier = @"tremor.handQueenWave";
step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT", nil);
}
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2555,7 +2614,8 @@ NSString *const ORKTremorTestTurnWristStepIdentifier = @"tremor.handQueenWave";
step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT", nil);
}
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2605,7 +2665,8 @@ NSString *const ORKTremorTestTurnWristStepIdentifier = @"tremor.handQueenWave";
step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT", nil);
}
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2653,7 +2714,8 @@ NSString *const ORKTremorTestTurnWristStepIdentifier = @"tremor.handQueenWave";
step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT", nil);
}
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2723,7 +2785,8 @@ NSString *const ORKTremorTestTurnWristStepIdentifier = @"tremor.handQueenWave";
step.image = [step.image ork_flippedImage:UIImageOrientationUpMirrored];
}
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
@@ -2880,7 +2943,8 @@ NSString *const ORKTrailmakingStepIdentifier = @"trailmaking";
step.image = [UIImage imageNamed:@"trailmaking" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2895,7 +2959,8 @@ NSString *const ORKTrailmakingStepIdentifier = @"trailmaking";
step.image = [UIImage imageNamed:@"trailmaking" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
@@ -2911,7 +2976,8 @@ NSString *const ORKTrailmakingStepIdentifier = @"trailmaking";
step.image = [UIImage imageNamed:@"trailmaking" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
step.imageContentMode = UIViewContentModeCenter;
step.shouldTintImages = YES;
step.shouldAutomaticallyAdjustImageTintColor = YES;
ORKStepArrayAddStep(steps, step);
}
}
+2
View File
@@ -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
+3 -1
View File
@@ -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;
+6
View File
@@ -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
@@ -92,7 +92,6 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
ORKQuestionStepCellHolderView *_cellHolderView;
id _defaultAnswer;
BOOL _visible;
UITableViewCell *_currentFirstResponderCell;
}
@@ -147,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;
}
@@ -157,7 +158,7 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
_answerFormat = [self.questionStep impliedAnswerFormat];
self.hasChangedAnswer = NO;
if ([self isViewLoaded]) {
BOOL neediPadDesign = ORKNeedWideScreenDesign(self.view);
[_tableContainer removeFromSuperview];
@@ -424,7 +425,6 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
- (void)viewDidLoad {
[super viewDidLoad];
[self stepDidChange];
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
@@ -446,10 +446,18 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
if (_tableView) {
[self.taskViewController setRegisteredScrollView:_tableView];
}
[self requestAndRefreshDefaults];
if (_tableView) {
[_tableView reloadData];
}
}
- (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];
@@ -472,7 +480,7 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
if (!scheduledRefresh) {
[self refreshDefaults];
}
#endif
if (_tableView) {
[_tableView reloadData];
}
@@ -514,12 +522,15 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
- (void)defaultAnswerDidChange {
id defaultAnswer = _defaultAnswer;
if (![self hasAnswer] && defaultAnswer && !self.hasChangedAnswer) {
_answer = defaultAnswer;
[self answerDidChange];
[self updateAnswer:defaultAnswer];
}
}
- (void)updateAnswer:(id)answer {
_answer = answer;
[self answerDidChange];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
@@ -1003,6 +1014,10 @@ static const NSTimeInterval DelayBeforeAutoScroll = 0.25;
#pragma mark - ORKSurveyAnswerCellDelegate
- (void)testAnswerDidChangeTo:(id)answer {
[self answerCell:[ORKSurveyAnswerCell new] answerDidChangeTo:answer dueUserAction:YES];
}
- (void)answerCell:(ORKSurveyAnswerCell *)cell answerDidChangeTo:(id)answer dueUserAction:(BOOL)dueUserAction {
[self saveAnswer:answer];
-2
View File
@@ -48,8 +48,6 @@
if (self) {
if (steps) {
_steps = [steps copy];
} else {
_steps = @[];
}
_resultSource = resultSource;
_excludeInstructionSteps = NO;
+3
View File
@@ -116,6 +116,9 @@ ORK_EXTERN CGFloat ORKQuestionStepMinimumHeaderHeight;
/// Default CGFloat used for rounded corner radii for card view
ORK_EXTERN CGFloat ORKCardDefaultCornerRadii;
/// Default CGFloat used for rounded corner radii for image choice button image view
ORK_EXTERN CGFloat ORKImageChoiceButtonCornerRadii;
/// Default CGFloat used for border width for card view
ORK_EXTERN CGFloat ORKCardDefaultBorderWidth;
+1
View File
@@ -60,6 +60,7 @@ NSString *const ORKDoneButtonPressedKey = @"ORKDoneButtonPressed";
NSString *const ORKResetDoneButtonKey = @"ORKResetDoneButton";
CGFloat ORKQuestionStepMinimumHeaderHeight = 29.75;
CGFloat ORKCardDefaultCornerRadii = 10.0;
CGFloat ORKImageChoiceButtonCornerRadii = 5.0;
CGFloat ORKCardDefaultBorderWidth = 0.0;
CGFloat ORKCardDefaultFontSize = 25.0;
CGFloat ORKSurveyItemMargin = 16.0;
+6
View File
@@ -181,6 +181,12 @@ ORK_CLASS_AVAILABLE API_AVAILABLE(ios(11.0), watchos(6.0))
*/
@property (nonatomic, copy, nullable) UIImage *iconImage;
/**
A property that gates automatic tint color image changes based on appearance changes
like userInterfaceStyle changes, and set to NO by default.
*/
@property (nonatomic) BOOL shouldAutomaticallyAdjustImageTintColor;
/**
Whether to show progress for this step when it is presented. The default is YES.
*/
+5 -1
View File
@@ -118,6 +118,7 @@
step.iconImage = self.iconImage;
step.bodyItems = [_bodyItems copy];
step.earlyTerminationConfiguration = self.earlyTerminationConfiguration;
step.shouldAutomaticallyAdjustImageTintColor = _shouldAutomaticallyAdjustImageTintColor;
#endif
return step;
@@ -152,6 +153,7 @@
&& ORKEqualObjects(self.iconImage, castObject.iconImage)
&& ORKEqualObjects(self.bodyItems, castObject.bodyItems)
&& ORKEqualObjects(self.earlyTerminationConfiguration, castObject.earlyTerminationConfiguration)
&& _shouldAutomaticallyAdjustImageTintColor == castObject->_shouldAutomaticallyAdjustImageTintColor
#endif
);
}
@@ -160,7 +162,7 @@
// Ignore the task reference - it's not part of the content of the step.
return _identifier.hash ^ _title.hash ^ _text.hash ^ self.detailText.hash ^_headerTextAlignment ^ self.footnote.hash ^ (_optional ? 0xf : 0x0) ^ (_showsProgress ? 0xf : 0x0) ^ (_useExtendedPadding ? 0xf : 0x0)
#if TARGET_OS_IOS
^ _bodyItemTextAlignment ^ (_buildInBodyItems ? 0xf : 0x0) ^ _imageContentMode ^ _bodyItems.hash ^_earlyTerminationConfiguration.hash
^ _bodyItemTextAlignment ^ (_buildInBodyItems ? 0xf : 0x0) ^ _imageContentMode ^ _bodyItems.hash ^_earlyTerminationConfiguration.hash ^ (_shouldAutomaticallyAdjustImageTintColor ? 0xf : 0x0)
#endif
;
}
@@ -195,6 +197,7 @@
ORK_DECODE_OBJ_ARRAY(aDecoder, bodyItems, ORKBodyItem);
ORK_DECODE_BOOL(aDecoder, buildInBodyItems);
ORK_DECODE_OBJ_CLASS(aDecoder, earlyTerminationConfiguration, ORKEarlyTerminationConfiguration);
ORK_DECODE_BOOL(aDecoder, shouldAutomaticallyAdjustImageTintColor);
#endif
}
return self;
@@ -221,6 +224,7 @@
ORK_ENCODE_OBJ(aCoder, bodyItems);
ORK_ENCODE_BOOL(aCoder, buildInBodyItems);
ORK_ENCODE_OBJ(aCoder, earlyTerminationConfiguration);
ORK_ENCODE_BOOL(aCoder, shouldAutomaticallyAdjustImageTintColor);
#endif
if ([_task isKindOfClass:[ORKOrderedTask class]]) {
ORK_ENCODE_OBJ(aCoder, task);
+2
View File
@@ -67,6 +67,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) BOOL useExtendedPadding;
@property (nonatomic) BOOL shouldAutomaticallyAdjustImageTintColor;
@property (nonatomic, weak) id<ORKStepContentLearnMoreItemDelegate> delegate;
- (instancetype)initWithStandardPadding;
+27 -1
View File
@@ -36,7 +36,7 @@
#import "ORKCompletionCheckmarkView.h"
#import "ORKBodyContainerView.h"
#import "ORKSkin.h"
#import "UIImageView+ResearchKit.h"
/*
+_________________________+
@@ -177,9 +177,34 @@ typedef NS_CLOSED_ENUM(NSInteger, ORKUpdateConstraintSequence) {
_topContentImageView.image = [self topContentAndAuxiliaryImage];
}
[self updateViewColors];
[[NSNotificationCenter defaultCenter] postNotificationName:ORKStepTopContentImageChangedKey object:nil];
}
- (void)setShouldAutomaticallyAdjustImageTintColor:(BOOL)shouldAutomaticallyAdjustImageTintColor {
_shouldAutomaticallyAdjustImageTintColor = shouldAutomaticallyAdjustImageTintColor;
[self updateViewColors];
}
- (void)updateViewColors {
if (!_shouldAutomaticallyAdjustImageTintColor) {
return;
}
if (@available(iOS 12.0, *)) {
[_topContentImageView updateRenderingModeForUserInterfaceStyle:self.traitCollection.userInterfaceStyle];
[_iconImageView updateRenderingModeForUserInterfaceStyle:self.traitCollection.userInterfaceStyle];
UIColor *imageViewTintColor = self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ? [UIColor whiteColor] : nil;
_topContentImageView.tintColor = imageViewTintColor;
_iconImageView.tintColor = imageViewTintColor;
}
}
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
[self updateViewColors];
}
- (void)setAuxiliaryImage:(UIImage *)auxiliaryImage {
_auxiliaryImage = auxiliaryImage;
if (_stepTopContentImage) {
@@ -299,6 +324,7 @@ typedef NS_CLOSED_ENUM(NSInteger, ORKUpdateConstraintSequence) {
_iconImageView.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:_iconImageView];
[self updateViewColors];
[self setIconImageViewConstraints];
}
@@ -43,6 +43,7 @@
#import "ORKSkin.h"
#import "ORKStepContentView.h"
#import "ORKEarlyTerminationConfiguration.h"
#import "UIBarButtonItem+ORKBarButtonItem.h"
static const CGFloat iPadStepTitleLabelPadding = 15.0;
static const CGFloat iPadStepTitleLabelFontSize = 50.0;
@@ -382,6 +383,16 @@ static const CGFloat iPadStepTitleLabelFontSize = 50.0;
return self.skipButtonItem.title;
}
- (void)enableBackNavigation {
[self setBackButtonItem:[self goToPreviousPageButtonItem]];
}
- (UIBarButtonItem *)goToPreviousPageButtonItem {
UIBarButtonItem *button = [UIBarButtonItem ork_backBarButtonItemWithTarget:self action:@selector(goBackward)];
button.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_BACK", nil);
return button;
}
- (void)setBackButtonItem:(UIBarButtonItem *)backButton {
backButton.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_BACK", nil);
_backButtonItem = backButton;
@@ -97,6 +97,9 @@ NS_ASSUME_NONNULL_BEGIN
// internal method for updating iPadBackgroundViewColor.
- (void)setiPadBackgroundViewColor:(UIColor *)color;
// internal method for enabling back navigation.
- (void)enableBackNavigation;
@end
#endif
@@ -76,10 +76,14 @@ static const CGFloat DontKnowButtonTopBottomPadding = 16.0;
_dontKnowButtonActive = NO;
ORKNumericAnswerFormat *numericAnswerFormat = (ORKNumericAnswerFormat *)self.step.answerFormat;
ORKAnswerFormat *answerFormat = self.step.answerFormat;
{
ORKNumericAnswerFormat *numericAnswerFormat = ORKDynamicCast(answerFormat, ORKNumericAnswerFormat);
_textFieldView.hideUnitWhenAnswerEmpty = numericAnswerFormat ? numericAnswerFormat.hideUnitWhenAnswerIsEmpty : NO;
}
_textFieldView = [[ORKTextFieldView alloc] init];
_textFieldView.hideUnitWhenAnswerEmpty = numericAnswerFormat.hideUnitWhenAnswerIsEmpty;
ORKUnitTextField *textField = _textFieldView.textField;
textField.delegate = self;
@@ -101,10 +105,10 @@ static const CGFloat DontKnowButtonTopBottomPadding = 16.0;
_errorLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_errorLabel];
if (numericAnswerFormat.shouldShowDontKnowButton) {
if (answerFormat.shouldShowDontKnowButton) {
if (!_dontKnowButton) {
_dontKnowButton = [ORKDontKnowButton new];
_dontKnowButton.customDontKnowButtonText = numericAnswerFormat.customDontKnowButtonText;
_dontKnowButton.customDontKnowButtonText = answerFormat.customDontKnowButtonText;
_dontKnowButton.translatesAutoresizingMaskIntoConstraints = NO;
[_dontKnowButton addTarget:self action:@selector(dontKnowButtonWasPressed) forControlEvents:UIControlEventTouchUpInside];
}
+8 -1
View File
@@ -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.
+41 -32
View File
@@ -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) {
@@ -1498,6 +1498,8 @@ static NSString *const _ChildNavigationControllerRestorationKey = @"childNavigat
NSAssert(stepViewController != nil, @"A non-nil step should always generate a step view controller");
stepViewController.continueButtonTitle = ORKLocalizedString(@"BUTTON_SAVE", nil);
stepViewController.parentReviewStep = (ORKReviewStep *) reviewStepViewController.step;
[stepViewController enableBackNavigation];
stepViewController.skipButtonTitle = stepViewController.readOnlyMode ? ORKLocalizedString(@"BUTTON_READ_ONLY_MODE", nil) : ORKLocalizedString(@"BUTTON_CLEAR_ANSWER", nil);
if (stepViewController.parentReviewStep.isStandalone) {
stepViewController.navigationItem.title = stepViewController.parentReviewStep.title;
@@ -1583,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
@@ -0,0 +1,42 @@
/*
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 <ResearchKit/ResearchKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface ORKTextChoiceAnswerFormat (FormStepViewControllerAdditions)
/// Returns YES if only the last object in the receivers textChoices property is an ORKTextChoiceOther type.
- (BOOL)hasStandardTextChoiceOtherArrangement;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,49 @@
/*
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 "ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h"
#import "ORKAnswerFormat.h"
#import "ORKHelpers_Internal.h"
@implementation ORKTextChoiceAnswerFormat (FormStepViewControllerAdditions)
- (BOOL)hasStandardTextChoiceOtherArrangement {
NSMutableArray *otherTextChoices = [[NSMutableArray alloc] init];
BOOL isLastItemTextChoiceOther = [self.textChoices.lastObject isKindOfClass:[ORKTextChoiceOther class]];
for (ORKTextChoice *textChoice in self.textChoices) {
ORKTextChoiceOther *textChoiceOther = ORKDynamicCast(textChoice, ORKTextChoiceOther);
if (textChoiceOther) {
[otherTextChoices addObject:textChoiceOther];
}
}
return otherTextChoices.count == 1 && isLastItemTextChoiceOther;
}
@end
+22 -5
View File
@@ -97,7 +97,7 @@
ORKTextChoiceOther *textChoiceOther = (ORKTextChoiceOther *)textChoice;
choiceOtherViewCell.textView.placeholder = textChoiceOther.textViewPlaceholderText;
choiceOtherViewCell.textView.text = textChoiceOther.textViewText;
[choiceOtherViewCell hideTextView:textChoiceOther.textViewStartsHidden];
[self updateTextViewForChoiceOtherCell:choiceOtherViewCell withTextChoiceOther:textChoiceOther];
cell = choiceOtherViewCell;
} else {
@@ -126,10 +126,16 @@
}
- (void)updateTextViewForChoiceOtherCell:(ORKChoiceOtherViewCell *)choiceCell withTextChoiceOther:(ORKTextChoiceOther *)choiceOther {
if (choiceOther.textViewStartsHidden && choiceCell.textView.text.length <= 0) {
[choiceCell hideTextView:!choiceCell.textViewHidden];
[self.delegate tableViewCellHeightUpdated];
BOOL shouldHideTextView = NO;
if(choiceOther.textViewStartsHidden) {
if(choiceCell.textView.text.length <= 0) {
shouldHideTextView = (choiceCell.isCellSelected == NO);
}
}
[choiceCell hideTextView:shouldHideTextView];
[self.delegate tableViewCellHeightUpdated];
}
- (void)textViewDidResignResponderForCellAtIndexPath:(NSIndexPath *)indexPath {
@@ -164,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;
@@ -172,9 +181,17 @@
if (_singleChoice) {
[touchedCell setCellSelected:YES highlight:YES];
for (ORKChoiceViewCell *cell in _cells.allValues) {
for (NSNumber *key in _cells) {
ORKChoiceViewCell *cell = _cells[key];
if (cell != touchedCell) {
ORKChoiceOtherViewCell *otherViewCell = ORKDynamicCast(cell, ORKChoiceOtherViewCell);
ORKTextChoice *cellTextChoice = [_helper textChoiceAtIndex:key.intValue];
ORKTextChoiceOther *textChoiceOther = ORKDynamicCast(cellTextChoice, ORKTextChoiceOther);
[cell setCellSelected:NO highlight:NO];
if (otherViewCell != nil && textChoiceOther != nil) {
[self updateTextViewForChoiceOtherCell:otherViewCell withTextChoiceOther:textChoiceOther];
}
}
}
} else {
+2 -1
View File
@@ -255,7 +255,8 @@ static const CGFloat PickerMinimumHeight = 34.0;
- (void)pickerWillAppear {
// Report current value, since ORKWeightPicker always has a value
[self pickerView];
[self valueDidChange:self];
// only do the assignment that's done in `valueDidChange`
_answer = [self selectedAnswerValue];
[self accessibilityFocusOnPickerElement];
}
-1
View File
@@ -79,7 +79,6 @@ struct TextChoiceView: View {
var dividerPadding: CGFloat = 20
dividerPadding += (imageWidth + 16)
return dividerPadding
}
+1
View File
@@ -35,5 +35,6 @@
@interface UIImage (ResearchKit)
- (UIImage *)ork_flippedImage:(UIImageOrientation)orientation;
- (UIImage *)ork_imageWithRenderingModeForUserInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle API_AVAILABLE(ios(12.0));
@end
+4
View File
@@ -116,4 +116,8 @@
}
}
- (UIImage *)ork_imageWithRenderingModeForUserInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle {
return userInterfaceStyle == UIUserInterfaceStyleDark ? [self imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] : [self imageWithRenderingMode:UIImageRenderingModeAutomatic];
}
@end
@@ -0,0 +1,41 @@
/*
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 <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImageView (ResearchKit)
- (void)updateRenderingModeForUserInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle API_AVAILABLE(ios(12.0));
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,40 @@
/*
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 "UIImage+ResearchKit.h"
#import "UIImageView+ResearchKit.h"
@implementation UIImageView (ResearchKit)
- (void)updateRenderingModeForUserInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle {
self.image = [self.image ork_imageWithRenderingModeForUserInterfaceStyle:userInterfaceStyle];
}
@end
@@ -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.9
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>
-1
View File
@@ -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>
+6
View File
@@ -1326,6 +1326,9 @@
XCTAssertEqual([[answerFormat defaultComponents] month], 01);
XCTAssertEqual([[answerFormat defaultComponents] day], 24);
XCTAssertEqual([[answerFormat defaultComponents] year], 1984);
//check that `hideUnitWhenAnswerIsEmpty` only works on `ORKNumericAnswerFormat`
XCTAssertThrows([(ORKNumericAnswerFormat*)answerFormat hideUnitWhenAnswerIsEmpty]);
}
- (void)testNumericAnswerFormat {
@@ -1342,6 +1345,7 @@
XCTAssertEqual([answerFormatWithIntegerStyle maximum], [NSNumber numberWithInteger:100]);
XCTAssertEqual([answerFormatWithIntegerStyle maximumFractionDigits], @(0));
XCTAssertTrue([answerFormatWithIntegerStyle hideUnitWhenAnswerIsEmpty]);
ORKNumericAnswerFormat *answerFormatWithDecimalStyle = [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleDecimal];
XCTAssertEqual([answerFormatWithDecimalStyle style ], ORKNumericAnswerStyleDecimal);
@@ -1505,6 +1509,7 @@
XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:1] value], [NSNumber numberWithInteger:2]);
}
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
- (void)testHealthKitCharacteristicTypeAnswerFormat {
HKCharacteristicType *biologicalSex = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex];
@@ -1592,6 +1597,7 @@
XCTAssertEqual([answerFormat numericAnswerStyle], ORKNumericAnswerStyleInteger);
XCTAssertEqual([answerFormat quantityType], calories);
}
#endif
- (void)testDateAnswerFormat {
@@ -0,0 +1,44 @@
/*
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 <ResearchKit/ORKFormStepViewController.h>
NS_ASSUME_NONNULL_BEGIN
@interface ORKFormStepViewController ()
- (void)restoreTextChoiceOtherCellStateWithSavedAnswer:(NSArray *)savedAnswer
formItem:(ORKFormItem *)formItem
choiceOtherViewCell:(ORKChoiceOtherViewCell *)choiceOtherViewCell;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,166 @@
/*
Copyright (c) 2019, 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 XCTest
import ResearchKit
class ORKFormStepViewControllerORKTextChoiceOtherRestorationTests: XCTestCase {
var formStepWithSingleTextChoiceOther: ORKFormStep {
let step = ORKFormStep(
identifier: "formstep",
title: "formStep",
text: nil
)
step.formItems = [
ORKFormItem(
identifier: "item1",
text: "item1",
answerFormat:
ORKTextChoiceAnswerFormat(
style:.singleChoice,
textChoices: [
ORKTextChoice(
text: "option1",
value: 1 as NSNumber
),
ORKTextChoiceOther.choice(
withText: "choice 8",
detailText: "",
value: 8 as NSNumber,
exclusive: true,
textViewPlaceholderText: "Tap to write your answer"
)
]
)
)
]
return step
}
var formStepWithMultipleTextChoiceOther: ORKFormStep {
let step = ORKFormStep(
identifier: "formstep",
title: "formStep",
text: nil
)
step.formItems = [
ORKFormItem(
identifier: "item1",
text: "item1",
answerFormat:
ORKTextChoiceAnswerFormat(
style: .singleChoice,
textChoices: [
ORKTextChoice(text: "option1", value: 1 as NSNumber),
ORKTextChoiceOther.choice(
withText: "choice 8",
detailText: "",
value: 8 as NSNumber,
exclusive: true,
textViewPlaceholderText: "Tap to write your answer"
),
ORKTextChoiceOther.choice(
withText: "choice 9",
detailText: "", value: 9 as NSNumber,
exclusive: true,
textViewPlaceholderText: "Tap to write your answer"
)
]
)
)
]
return step
}
func testORKChoiceRestorationWithSingleTextChoiceOther() {
let step = formStepWithSingleTextChoiceOther
let formStepViewController = ORKFormStepViewController(step: step)
let savedAnswers = ["text"]
formStepViewController.restoreTextChoiceOtherCellState(
withSavedAnswer: savedAnswers,
formItem: step.formItems!.last!,
choiceOtherViewCell: ORKChoiceOtherViewCell()
)
checkTextChoiceRestoredCorrectly(
step: step,
hasStandardTextChoiceOtherArrangement: true,
expectedRestoredTextViewText: "text"
)
}
func testORKChoiceRestorationWithMultipleTextChoiceOther() {
let step = formStepWithMultipleTextChoiceOther
let formStepViewController = ORKFormStepViewController(step: step)
let savedAnswers = ["text"]
formStepViewController.restoreTextChoiceOtherCellState(
withSavedAnswer: savedAnswers,
formItem: step.formItems!.first!,
choiceOtherViewCell: ORKChoiceOtherViewCell()
)
checkTextChoiceRestoredCorrectly(
step: step,
hasStandardTextChoiceOtherArrangement: false,
expectedRestoredTextViewText: nil
)
}
func checkTextChoiceRestoredCorrectly(step: ORKFormStep, hasStandardTextChoiceOtherArrangement: Bool, expectedRestoredTextViewText: String?) {
guard let formItems = step.formItems else {
XCTFail("No formItems found")
return
}
guard let firstFormItem = formItems.first else {
XCTFail("No formItems found")
return
}
guard let firstFormItemAnswerFormat = firstFormItem.answerFormat else {
XCTFail("No answerFormat found")
return
}
let textChoiceAnswerFormat = firstFormItemAnswerFormat as! ORKTextChoiceAnswerFormat
XCTAssertEqual(textChoiceAnswerFormat.hasStandardTextChoiceOtherArrangement(), hasStandardTextChoiceOtherArrangement)
guard let lastTextChoiceOther = textChoiceAnswerFormat.textChoices.last as? ORKTextChoiceOther else {
XCTFail("No textChoiceOthers found")
return
}
if let expectedRestoredTextViewText = expectedRestoredTextViewText {
XCTAssertEqual(lastTextChoiceOther.textViewText, expectedRestoredTextViewText)
} else {
XCTAssertEqual(lastTextChoiceOther.textViewText, nil)
}
}
}
+2 -1
View File
@@ -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
@@ -0,0 +1,134 @@
/*
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 XCTest
import ResearchKit.Private
#if ORK_FEATURE_HEALTHKIT_AUTHORIZATION
final class ORKHealthKitQuestionStepViewControllerTests: XCTestCase {
var testController: ORKStepViewController!
var step: ORKStep!
var result: ORKResult!
var negativeTest: Bool!
var forwardExpectation: XCTestExpectation!
var reverseExpectation: XCTestExpectation!
var appearExpectation: XCTestExpectation!
var failExpectation: XCTestExpectation!
var recorderExpectation: XCTestExpectation!
var testingWillExpectation: Bool!
var utilities: TopLevelUIUtilities<ORKStepViewController>!
private let weight = HKObjectType.quantityType(forIdentifier: .bodyMass)!
override func setUp() {
super.setUp()
negativeTest = false
testingWillExpectation = false
step = ORKStep(identifier: "STEP")
result = ORKResult(identifier: "RESULT")
testController = ORKStepViewController(step: step, result: result)
testController.delegate = self
utilities = TopLevelUIUtilities<ORKStepViewController>()
utilities.setupTopLevelUI(withViewController: testController)
}
func testHealthKitAnswerFormats() {
let healthAnswerFormats = [
ORKHealthKitQuantityTypeAnswerFormat(quantityType: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!, unit: HKUnit.gramUnit(with: .kilo), style: .decimal),
ORKHealthKitQuantityTypeAnswerFormat(quantityType: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!, unit: HKUnit.meterUnit(with: .centi), style: .integer)
]
for answerFormat in healthAnswerFormats {
let healthKitStep = ORKQuestionStep(identifier: String(describing: "HealthKitStep"), title: NSLocalizedString("Some Title", comment: ""), question: "Some Question", answer: answerFormat)
helperTestHealthKit(healthKitStep: healthKitStep)
}
}
func helperTestHealthKit(healthKitStep: ORKQuestionStep) {
testController = ORKQuestionStepViewController(step: healthKitStep)
testController.delegate = self
utilities = TopLevelUIUtilities<ORKStepViewController>()
utilities.setupTopLevelUI(withViewController: testController)
testController.stepDidChange()
// Test that [self hasAnswer] && self.hasChangedAnswer are false
XCTAssertNil((testController as! ORKQuestionStepViewController).answer())
XCTAssertFalse((testController as! ORKQuestionStepViewController).hasChangedAnswer())
// Simulating picker update to a value of 50
(testController as! ORKQuestionStepViewController).testAnswerDidChange(to: 50.0)
// Test that [self hasAnswer] has a value
XCTAssertEqual((testController as! ORKQuestionStepViewController).answer() as! Double, 50.0)
// && self.hasChangedAnswer is true
XCTAssertTrue((testController as! ORKQuestionStepViewController).hasChangedAnswer())
}
}
extension ORKHealthKitQuestionStepViewControllerTests: ORKStepViewControllerDelegate {
func stepViewController(_ stepViewController: ORKStepViewController, didFinishWith direction: ORKStepViewControllerNavigationDirection) {
if direction == .forward {
forwardExpectation.fulfill()
} else {
reverseExpectation.fulfill()
}
}
func stepViewControllerWillAppear(_ stepViewController: ORKStepViewController) {
if testingWillExpectation {
appearExpectation.fulfill()
}
}
func stepViewControllerResultDidChange(_ stepViewController: ORKStepViewController) {
// pass
}
func stepViewControllerDidFail(_ stepViewController: ORKStepViewController, withError error: Error?) {
failExpectation.fulfill()
}
func stepViewController(_ stepViewController: ORKStepViewController, recorder: ORKRecorder, didFailWithError error: Error) {
recorderExpectation.fulfill()
}
func stepViewControllerHasNextStep(_ stepViewController: ORKStepViewController) -> Bool {
if negativeTest { return false }
return true
}
func stepViewControllerHasPreviousStep(_ stepViewController: ORKStepViewController) -> Bool {
if negativeTest { return false }
return true
}
}
#endif
@@ -0,0 +1,48 @@
/*
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 <ResearchKit/ORKQuestionStepViewController.h>
NS_ASSUME_NONNULL_BEGIN
@interface ORKQuestionStepViewController () <ORKQuestionStepCustomViewDelegate>
- (nullable id)answer;
- (BOOL)hasChangedAnswer;
/**
Set the step answer.
*/
- (void)testAnswerDidChangeTo:(id)answer;
@end
NS_ASSUME_NONNULL_END
+21 -2
View File
@@ -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
+4 -2
View File
@@ -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);
+31
View File
@@ -33,6 +33,7 @@
@import ResearchKit;
@import ResearchKit.Private;
@import UIKit;
#import "ORKReviewStep_Internal.h"
@interface ORKStepTests : XCTestCase
@@ -571,3 +572,33 @@
}
@end
@interface ORKReviewStepTests : XCTestCase
@end
@implementation ORKReviewStepTests
// ORKReviewStep's implementation of `isStandalone` is
// return _steps != nil;
- (void)testEmbeddedReviewStep {
// test that embeddedReviewStep always has isStandalone set to false
ORKReviewStep* embeddedReviewStep = [ORKReviewStep embeddedReviewStepWithIdentifier:@"embeddedReviewStep"];
XCTAssertFalse(embeddedReviewStep.isStandalone);
// test that standaloneReviewStep with nil steps has isStandalone set to false
ORKReviewStep* standAloneReviewStepWithNilSteps = [ORKReviewStep standaloneReviewStepWithIdentifier:@"standAloneReviewStepWithNilSteps" steps:nil resultSource:nil];
XCTAssertFalse(standAloneReviewStepWithNilSteps.isStandalone);
}
- (void)testStandAloneReviewStep {
// test that standaloneReviewStep with non nil steps always has isStandalone set to true
ORKReviewStep* standAloneReviewStep = [ORKReviewStep standaloneReviewStepWithIdentifier:@"standAloneReviewStep" steps:@[] resultSource:nil];
XCTAssertTrue(standAloneReviewStep.isStandalone);
// test that standaloneReviewStep with defined steps always has isStandalone set to true
ORKReviewStep* standAloneReviewStepWithSteps = [ORKReviewStep standaloneReviewStepWithIdentifier:@"standAloneReviewStep" steps:@[[[ORKInstructionStep alloc] initWithIdentifier:@"instructionStep"]] resultSource:nil];
XCTAssertTrue(standAloneReviewStepWithSteps.isStandalone);
}
@end
+17 -5
View File
@@ -1438,9 +1438,10 @@ static ORKStepResult *(^getConsentStepResult)(NSString *, NSString *, BOOL) = ^O
- (void)testTaskViewControllerCanDiscardLogic {
TestTaskViewControllerDelegate *delegate = [[TestTaskViewControllerDelegate alloc] init];
ORKStep *reviewableStep = [ORKQuestionStep questionStepWithIdentifier:@"Who's there?" title:nil question:nil answer:nil];
ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:@"TestTask" steps:@[
[[ORKInstructionStep alloc] initWithIdentifier:@"instuction-0"],
[ORKReviewStep standaloneReviewStepWithIdentifier:@"review" steps:nil resultSource:nil],
[ORKReviewStep standaloneReviewStepWithIdentifier:@"review" steps:@[reviewableStep] resultSource:nil],
]];
// test cases where hasSaveableResults == NO
@@ -1463,7 +1464,7 @@ static ORKStepResult *(^getConsentStepResult)(NSString *, NSString *, BOOL) = ^O
XCTAssertTrue([reviewStep isStandalone]);
XCTAssertTrue([taskViewController canDiscardResults]);
}
// test cases where hasSaveableResults == YES
{
MockTaskViewController *taskViewController = [[MockTaskViewController alloc] initWithTask:task taskRunUUID:nil];
@@ -1504,10 +1505,7 @@ static ORKStepResult *(^getConsentStepResult)(NSString *, NSString *, BOOL) = ^O
ORKReviewStepViewController *reviewViewController = ORKDynamicCast(taskViewController.currentStepViewController, ORKReviewStepViewController);
XCTAssertNotNil(reviewViewController, "taskViewController.currentStepViewController should be of type ORKReviewStepViewController at this point");
// [TODO]:Test if currentStep is reviewStep but not standalone -> CANNOT discardResults
// before reviewStepViewController:willReviewStep, currentStepViewController should not be in readOnlyMode
XCTAssertFalse(taskViewController.currentStepViewController.readOnlyMode);
@@ -1537,6 +1535,20 @@ static ORKStepResult *(^getConsentStepResult)(NSString *, NSString *, BOOL) = ^O
}
- (void)testTaskViewControllerReviewStepDiscardLogic {
ORKReviewStep *embeddedReviewStep = [ORKReviewStep embeddedReviewStepWithIdentifier: @"embeddedReviewStep"];
ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:@"embeddedReviewMockTask"
steps:@[
embeddedReviewStep
]];
MockTaskViewController *taskViewController = [[MockTaskViewController alloc] initWithTask:task taskRunUUID:nil];
[taskViewController viewWillAppear:false];
// Test if currentStep is reviewStep but not standalone -> CANNOT discardResults
XCTAssertFalse(embeddedReviewStep.isStandalone);
XCTAssertFalse([taskViewController canDiscardResults]);
}
- (void)testIndexOfStep {
ORKOrderedTask *task = [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:@"tapping" intendedUseDescription:nil duration:30 handOptions:0 options:0];
@@ -4,3 +4,7 @@
#import "ResearchKit.h"
#import "ResearchKit_Private.h"
#import "ORKQuestionStepViewController+TestingSupport.h"
#import "ORKFormStepViewController+TestingSupport.h"
#import "ORKAnswerFormat_Internal.h"
#import "ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h"
@@ -896,6 +896,7 @@ static NSMutableDictionary<NSString *, ORKESerializableTableEntry *> *ORKESerial
PROPERTY(buildInBodyItems, NSNumber, NSObject, YES, nil, nil),
PROPERTY(useExtendedPadding, NSNumber, NSObject, YES, nil, nil),
PROPERTY(earlyTerminationConfiguration, ORKEarlyTerminationConfiguration, NSObject, YES, nil, nil),
PROPERTY(shouldAutomaticallyAdjustImageTintColor, NSNumber, NSObject, YES, nil, nil),
})),
ENTRY(ORKBodyItem,
^id(__unused NSDictionary *dict, __unused ORKESerializationPropertyGetter getter) {
@@ -1 +1 @@
{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"50DE67FB-AE5A-4C1A-97E6-038BAB9A346F"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"23DBF489-731A-446A-A5ED-3D3E737C5E12"},"title":"","image":{"imageName":"A39F0D25-B88E-446C-BC34-614AE0405E73"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment":0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORK3DModelStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0, "modelManager": {"_class":"ORK3DModelManager", "allowsSelection":false, "identifiersOfObjectsToHighlight":[], "highlightColor": {"r":1, "g":1, "b":1, "a":1 }},"earlyTerminationConfiguration": {"_class": "ORKEarlyTerminationConfiguration"}}
{"footnote":"","shouldAutomaticallyAdjustImageTintColor":0,"shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"50DE67FB-AE5A-4C1A-97E6-038BAB9A346F"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"23DBF489-731A-446A-A5ED-3D3E737C5E12"},"title":"","image":{"imageName":"A39F0D25-B88E-446C-BC34-614AE0405E73"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment":0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORK3DModelStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0, "modelManager": {"_class":"ORK3DModelManager", "allowsSelection":false, "identifiersOfObjectsToHighlight":[], "highlightColor": {"r":1, "g":1, "b":1, "a":1 }},"earlyTerminationConfiguration": {"_class": "ORKEarlyTerminationConfiguration"}}
@@ -1 +1 @@
{"footnote":"","shouldContinueOnFinish":true,"shouldTintImages":true,"shouldSpeakCountDown":false,"recorderConfigurations":[],"iconImage":{"imageName":"62E9D4CF-3E7B-49B8-A295-7D2EB1ECC00B"},"auxiliaryImage":{"imageName":"8C25AB92-00C9-4E13-B55F-711658F53D48"},"title":"","image":{"imageName":"4930AC43-8AAA-4563-8C8F-6E7E25E550C3"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":9.2233720368547758e+18,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":true,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAccuracyStroopStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration":{"_class":"ORKEarlyTerminationConfiguration"}, "baseDisplayColor":{"r":1,"g":1,"b":1,"a":1}, "isColorMatching":false}
{"footnote":"","shouldAutomaticallyAdjustImageTintColor":0,"shouldContinueOnFinish":true,"shouldTintImages":true,"shouldSpeakCountDown":false,"recorderConfigurations":[],"iconImage":{"imageName":"62E9D4CF-3E7B-49B8-A295-7D2EB1ECC00B"},"auxiliaryImage":{"imageName":"8C25AB92-00C9-4E13-B55F-711658F53D48"},"title":"","image":{"imageName":"4930AC43-8AAA-4563-8C8F-6E7E25E550C3"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":9.2233720368547758e+18,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":true,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAccuracyStroopStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration":{"_class":"ORKEarlyTerminationConfiguration"}, "baseDisplayColor":{"r":1,"g":1,"b":1,"a":1}, "isColorMatching":false}
@@ -1 +1 @@
{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"50DE67FB-AE5A-4C1A-97E6-038BAB9A346F"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"23DBF489-731A-446A-A5ED-3D3E737C5E12"},"title":"","image":{"imageName":"A39F0D25-B88E-446C-BC34-614AE0405E73"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment":0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKActiveStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration":{"_class":"ORKEarlyTerminationConfiguration"}}
{"footnote":"","shouldAutomaticallyAdjustImageTintColor":0,"shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"50DE67FB-AE5A-4C1A-97E6-038BAB9A346F"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"23DBF489-731A-446A-A5ED-3D3E737C5E12"},"title":"","image":{"imageName":"A39F0D25-B88E-446C-BC34-614AE0405E73"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment":0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKActiveStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration":{"_class":"ORKEarlyTerminationConfiguration"}}
@@ -1 +1 @@
{"footnote":"","shouldContinueOnFinish":true,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"DFC4815F-FB55-4365-9D10-FF2BA83879A1"},"auxiliaryImage":{"imageName":"3E076C04-09E0-4055-8FBE-5309DC4A5348"},"title":"","image":{"imageName":"0905D188-3CBD-4DEE-82C7-11165BA8352B"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0,"stepDuration":9.2233720368547758e+18,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","eyeSide":0,"optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"shouldVibrateOnStart":true,"bodyItems":[],"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAmslerGridStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration": {"_class": "ORKEarlyTerminationConfiguration"}}
{"footnote":"","shouldAutomaticallyAdjustImageTintColor":0,"shouldContinueOnFinish":true,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"DFC4815F-FB55-4365-9D10-FF2BA83879A1"},"auxiliaryImage":{"imageName":"3E076C04-09E0-4055-8FBE-5309DC4A5348"},"title":"","image":{"imageName":"0905D188-3CBD-4DEE-82C7-11165BA8352B"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0,"stepDuration":9.2233720368547758e+18,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","eyeSide":0,"optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"shouldVibrateOnStart":true,"bodyItems":[],"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAmslerGridStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration": {"_class": "ORKEarlyTerminationConfiguration"}}
@@ -1 +1 @@
{"vocalCues":[{"_class":"ORKVocalCue","time": 12,"spokenText":"words"}, {"_class":"ORKVocalCue","time": 13,"spokenText":"more words"}],"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"3F5C9800-6A7A-4158-8ECF-0832B44DF6C1"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"988B687D-F50F-4B89-B6B7-20F11AE6AC8E"},"title":"","image":{"imageName":"B7400237-AD21-4AA3-8E4C-60F06E05EA39"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0, "stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAudioFitnessStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration": {"_class": "ORKEarlyTerminationConfiguration"},"userInfo":{},"audioAsset":{"_class":"ORKBundleAsset","name":"filename","bundleIdentifier":"com.bundle.identifier","fileExtension":"mp4"}}
{"vocalCues":[{"_class":"ORKVocalCue","time": 12,"spokenText":"words"}, {"_class":"ORKVocalCue","time": 13,"spokenText":"more words"}],"footnote":"","shouldAutomaticallyAdjustImageTintColor":0,"shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"3F5C9800-6A7A-4158-8ECF-0832B44DF6C1"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"988B687D-F50F-4B89-B6B7-20F11AE6AC8E"},"title":"","image":{"imageName":"B7400237-AD21-4AA3-8E4C-60F06E05EA39"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0, "stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAudioFitnessStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration": {"_class": "ORKEarlyTerminationConfiguration"},"userInfo":{},"audioAsset":{"_class":"ORKBundleAsset","name":"filename","bundleIdentifier":"com.bundle.identifier","fileExtension":"mp4"}}
@@ -1 +1 @@
{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"244AD43E-7785-4BF5-829C-A3B5C771E9F2"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"A35CAC85-9557-4ED5-9807-DCFDAC04C81D"},"title":"","image":{"imageName":"5E598B50-21DC-400E-8D80-75BB26BDCD65"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0,"stepDuration":0,"useRecordButton":false,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAudioStep","shouldStartTimerAutomatically":true,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration":{"_class":"ORKEarlyTerminationConfiguration"}}
{"footnote":"","shouldAutomaticallyAdjustImageTintColor":0,"shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"244AD43E-7785-4BF5-829C-A3B5C771E9F2"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"A35CAC85-9557-4ED5-9807-DCFDAC04C81D"},"title":"","image":{"imageName":"5E598B50-21DC-400E-8D80-75BB26BDCD65"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0,"stepDuration":0,"useRecordButton":false,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAudioStep","shouldStartTimerAutomatically":true,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"earlyTerminationConfiguration":{"_class":"ORKEarlyTerminationConfiguration"}}
@@ -1 +1 @@
{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKCompletionStep","iconImage":{"imageName":"2A7001B3-FE8B-4628-B9A3-848BBEF58B1F"},"auxiliaryImage":{"imageName":"685A4968-7933-4BCE-A646-9EBE32A63514"},"title":"","identifier":"","image":{"imageName":"7469F374-6BCA-4716-8BF1-AFF1761E6DE2"},"footnote":"","text":"","detailText":"", "headerTextAlignment": 0,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"centerImageVertically":0,"useExtendedPadding":0, "reasonForCompletion":0,"earlyTerminationConfiguration":{"_class":"ORKEarlyTerminationConfiguration"}}
{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKCompletionStep","iconImage":{"imageName":"2A7001B3-FE8B-4628-B9A3-848BBEF58B1F"},"auxiliaryImage":{"imageName":"685A4968-7933-4BCE-A646-9EBE32A63514"},"title":"","identifier":"","image":{"imageName":"7469F374-6BCA-4716-8BF1-AFF1761E6DE2"},"footnote":"","shouldAutomaticallyAdjustImageTintColor":0,"text":"","detailText":"", "headerTextAlignment": 0,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"centerImageVertically":0,"useExtendedPadding":0, "reasonForCompletion":0,"earlyTerminationConfiguration":{"_class":"ORKEarlyTerminationConfiguration"}}

Some files were not shown because too many files have changed in this diff Show More