Compare commits
2 Commits
2.2.12-dev
...
2.2.15-dev
| Author | SHA1 | Date | |
|---|---|---|---|
| a07041901b | |||
| c370011616 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'ResearchKit'
|
||||
s.version = '2.1.0'
|
||||
s.version = '2.2.15'
|
||||
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/'
|
||||
|
||||
@@ -55,6 +55,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, ); }; };
|
||||
@@ -1045,9 +1048,9 @@
|
||||
05F3765923C797930068E166 /* ResearchKit.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = ResearchKit.xctestplan; 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>"; };
|
||||
0B7D32E92AE6F8040071C576 /* ORKQuestionStepViewController+TestingSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ORKQuestionStepViewController+TestingSupport.h"; 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>"; };
|
||||
@@ -1059,6 +1062,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>"; };
|
||||
@@ -3129,6 +3136,7 @@
|
||||
86CC8EA81AC09383001CCD89 /* ORKAccessibilityTests.m */,
|
||||
248604051B4C98760010C8A0 /* ORKAnswerFormatTests.m */,
|
||||
0B7D32E92AE6F8040071C576 /* ORKQuestionStepViewController+TestingSupport.h */,
|
||||
0BC8034D2B07F60600618E4F /* ORKFormStepViewController+TestingSupport.h */,
|
||||
0B59A6BD28C1738D005035B4 /* ORKPickerTestDelegate.h */,
|
||||
0B59A6BE28C1738D005035B4 /* ORKPickerTestDelegate.m */,
|
||||
86CC8EA91AC09383001CCD89 /* ORKChoiceAnswerFormatHelperTests.m */,
|
||||
@@ -3150,6 +3158,7 @@
|
||||
1490DD01224D6A21003FEEDA /* ORKResultPredicateTests.swift */,
|
||||
1490DD03224D6A61003FEEDA /* ORKTestResultPredicateType.swift */,
|
||||
14F7AC8A2269035200D52F41 /* ORKStepViewControllerTests.swift */,
|
||||
0BC8034E2B07F6B100618E4F /* ORKFormStepViewControllerORKTextChoiceOtherRestorationTests.swift */,
|
||||
0BA0F4B12A1C1FD300A55672 /* ORKHealthKitQuestionStepViewControllerTests.swift */,
|
||||
14E7903F226A5F72009D8083 /* ORKStepViewControllerHelpers.swift */,
|
||||
);
|
||||
@@ -3467,6 +3476,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 */,
|
||||
@@ -4562,6 +4573,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 */,
|
||||
@@ -5014,6 +5026,7 @@
|
||||
714151D0225C4A23002CA33B /* ORKPasscodeViewControllerTests.swift in Sources */,
|
||||
0324C1D825439E1800BBE77B /* ORKVideoInstructionStepViewControllerTests.swift in Sources */,
|
||||
14E79040226A5F72009D8083 /* ORKStepViewControllerHelpers.swift in Sources */,
|
||||
0BC803602B1578D500618E4F /* ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.m in Sources */,
|
||||
86D348021AC161B0006DB02B /* ORKRecorderTests.m in Sources */,
|
||||
1490DCFC224D4867003FEEDA /* ORKEnvironmentSPLMeterResultTests.swift in Sources */,
|
||||
7141EA2222EFBC0C00650145 /* ORKLoggingTests.m in Sources */,
|
||||
@@ -5021,6 +5034,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;
|
||||
@@ -5411,6 +5425,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 */,
|
||||
|
||||
@@ -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;
|
||||
@@ -468,6 +470,26 @@ 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 {
|
||||
NSArray *formItems = [self formItems];
|
||||
ORKAnswerDefaultSource *source = _defaultSource;
|
||||
@@ -1154,9 +1176,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 +1594,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];
|
||||
}
|
||||
|
||||
@@ -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 receiver’s 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
|
||||
@@ -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.isSelected == NO;
|
||||
}
|
||||
}
|
||||
|
||||
[choiceCell hideTextView:shouldHideTextView];
|
||||
[self.delegate tableViewCellHeightUpdated];
|
||||
}
|
||||
|
||||
- (void)textViewDidResignResponderForCellAtIndexPath:(NSIndexPath *)indexPath {
|
||||
@@ -172,9 +178,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 {
|
||||
|
||||
@@ -25,7 +25,7 @@ SYSTEM_FRAMEWORK_SEARCH_PATHS = $(inherited)
|
||||
SYSTEM_HEADER_SEARCH_PATHS = $(inherited)
|
||||
CLANG_STATIC_ANALYZER_MODE = deep
|
||||
|
||||
ORK_FRAMEWORK_VERSION_NUMBER = 2.2.12
|
||||
ORK_FRAMEWORK_VERSION_NUMBER = 2.2.15
|
||||
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,3 +5,6 @@
|
||||
#import "ResearchKit.h"
|
||||
#import "ResearchKit_Private.h"
|
||||
#import "ORKQuestionStepViewController+TestingSupport.h"
|
||||
#import "ORKFormStepViewController+TestingSupport.h"
|
||||
#import "ORKAnswerFormat_Internal.h"
|
||||
#import "ORKTextChoiceAnswerFormat+FormStepViewControllerAdditions.h"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// ORKCatalog-Shared.xcconfig
|
||||
//
|
||||
|
||||
ORK_CATALOG_VERSION_NUMBER = 2.2.12
|
||||
ORK_CATALOG_VERSION_NUMBER = 2.2.15
|
||||
|
||||
ORK_CATALOG_BUILD_NUMBER = $(ORK_CATALOG_BUILD_NUMBER_CI_$(CI)) // ORK_CATALOG_BUILD_NUMBER_CI_TRUE or ORK_CATALOG_BUILD_NUMBER_CI_
|
||||
ORK_CATALOG_BUILD_NUMBER_CI_TRUE = $(CI_BUILD_NUMBER) // if CI_BUILD_NUMBER is defined (presumably by CI) just use it
|
||||
|
||||
@@ -451,7 +451,8 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
case formItem02
|
||||
case formItem03
|
||||
case formItem04
|
||||
|
||||
case textChoiceFormItem
|
||||
|
||||
// Survey task specific identifiers.
|
||||
case surveyTask
|
||||
case introStep
|
||||
@@ -874,7 +875,7 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
scaleAnswerFormat.shouldHideRanges = true
|
||||
let formItem03 = ORKFormItem(identifier: String(describing: Identifier.formItem03), text: formItem03Text, answerFormat: scaleAnswerFormat)
|
||||
|
||||
let textChoices: [ORKTextChoice] = [
|
||||
var textChoices: [ORKTextChoice] = [
|
||||
ORKTextChoice(text: "choice 1", detailText: "detail 1", value: 1 as NSNumber, exclusive: false),
|
||||
ORKTextChoice(text: "choice 2", detailText: "detail 2", value: 2 as NSNumber, exclusive: false),
|
||||
ORKTextChoice(text: "choice 3", detailText: "detail 3", value: 3 as NSNumber, exclusive: false),
|
||||
@@ -882,12 +883,18 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
ORKTextChoice(text: "choice 5", detailText: "detail 5", value: 5 as NSNumber, exclusive: false),
|
||||
ORKTextChoice(text: "choice 6", detailText: "detail 6", value: 6 as NSNumber, exclusive: false)
|
||||
]
|
||||
|
||||
|
||||
let textScaleAnswerFormat = ORKTextScaleAnswerFormat(textChoices: textChoices, defaultIndex: 10)
|
||||
textScaleAnswerFormat.shouldHideLabels = true
|
||||
textScaleAnswerFormat.shouldShowDontKnowButton = true
|
||||
|
||||
textChoices.append(ORKTextChoiceOther.choice(withText: "choice 7", detailText: "", value: 7 as NSNumber, exclusive: true, textViewPlaceholderText: "Tap to write your answer"))
|
||||
let textChoiceAnswerFormat = ORKTextChoiceAnswerFormat(style: .singleChoice, textChoices: textChoices)
|
||||
|
||||
let formItem04 = ORKFormItem(identifier: String(describing: Identifier.formItem04), text: exampleQuestionText, answerFormat: textScaleAnswerFormat)
|
||||
|
||||
let textChoiceFormItem = ORKFormItem(identifier: String(describing: Identifier.textChoiceFormItem), text: exampleQuestionText, answerFormat: textChoiceAnswerFormat)
|
||||
|
||||
let appleChoices: [ORKTextChoice] = [ORKTextChoice(text: "Granny Smith", value: 1 as NSNumber), ORKTextChoice(text: "Honeycrisp", value: 2 as NSNumber), ORKTextChoice(text: "Fuji", value: 3 as NSNumber), ORKTextChoice(text: "McIntosh", value: 10 as NSNumber), ORKTextChoice(text: "Kanzi", value: 5 as NSNumber)]
|
||||
|
||||
let appleAnswerFormat = ORKTextChoiceAnswerFormat(style: .singleChoice, textChoices: appleChoices)
|
||||
@@ -907,6 +914,7 @@ enum TaskListRow: Int, CustomStringConvertible {
|
||||
formItem04,
|
||||
formItem01,
|
||||
formItem02,
|
||||
textChoiceFormItem,
|
||||
freeTextSection,
|
||||
freeTextItem
|
||||
]
|
||||
|
||||
@@ -274,7 +274,8 @@ class TaskListViewController: UITableViewController, ORKTaskViewControllerDelega
|
||||
let colorName = questionResult.choiceAnswers?.first as? String,
|
||||
let color = UIColor.value(forKey: colorName) as? UIColor
|
||||
else {
|
||||
fatalError("Couldn't create a color from question result \(questionResult)")
|
||||
// Couldn't create a color from question result -- may have been skipped
|
||||
return
|
||||
}
|
||||
|
||||
// Finally, set the tintColor
|
||||
|
||||
Reference in New Issue
Block a user