From 05b30cf8e51299ea4b4d9e8e38feaadcba531194 Mon Sep 17 00:00:00 2001 From: Gerardo Marx Date: Fri, 11 Oct 2024 18:29:44 -0600 Subject: [PATCH] Survey Task example working --- .gitignore | 61 ++++++++ .gitmodules | 3 + RK-Setup-Git.xcodeproj/project.pbxproj | 148 +++++++++++++++++- .../xcschemes/xcschememanagement.plist | 2 +- RK-Setup-Git/Base.lproj/Main.storyboard | 32 +++- RK-Setup-Git/SurveyTask.swift | 27 ++++ RK-Setup-Git/ViewController.swift | 62 +++++++- ResearchKit | 1 + 8 files changed, 326 insertions(+), 10 deletions(-) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 RK-Setup-Git/SurveyTask.swift create mode 160000 ResearchKit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b2e21b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# Xcode specific +.DS_Store +*.xcuserstate +*.xcscmblueprint +*.swp +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +# User-specific settings +xcuserdata/ +*.xcworkspace/xcuserdata/ + +# Xcode build +build/ +*.ipa +*.dSYM.zip +*.dSYM + +# CocoaPods +Pods/ +Podfile.lock + +# Carthage +Carthage/Build/ + +# Swift Package Manager +.build/ +DerivedData/ +SourcePackages/ +Package.resolved + +# Fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output + +# Generated files +*.moved-aside +*.hmap +*.ipa +*.xcuserdatad +*.localized +*.xcworkspacedata + +# Temporary and System files +*.tmp +*.log +*.swp +*.lock +*.lock/ +*.lck +*.sync + +# Playgrounds +timeline.xctimeline +playground.xcworkspace + +# SwiftPM +.swiftpm/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b4856b2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ResearchKit"] + path = ResearchKit + url = https://github.com/ResearchKit/ResearchKit.git diff --git a/RK-Setup-Git.xcodeproj/project.pbxproj b/RK-Setup-Git.xcodeproj/project.pbxproj index 86bf2a8..ddd6b0a 100644 --- a/RK-Setup-Git.xcodeproj/project.pbxproj +++ b/RK-Setup-Git.xcodeproj/project.pbxproj @@ -13,8 +13,73 @@ 7EE7BFA32CB8F25B0000161D /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 7EE7BFA22CB8F25B0000161D /* Base */; }; 7EE7BFA52CB8F25C0000161D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7EE7BFA42CB8F25C0000161D /* Assets.xcassets */; }; 7EE7BFA82CB8F25C0000161D /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 7EE7BFA72CB8F25C0000161D /* Base */; }; + 7EE7BFF62CB8FA1C0000161D /* SurveyTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EE7BFF52CB8FA1C0000161D /* SurveyTask.swift */; }; + 7EE7C01F2CB9E9D90000161D /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7EE7C0182CB9E60E0000161D /* ResearchKit.framework */; }; + 7EE7C0202CB9E9D90000161D /* ResearchKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7EE7C0182CB9E60E0000161D /* ResearchKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 7EE7C0212CB9E9D90000161D /* ResearchKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7EE7C01C2CB9E60E0000161D /* ResearchKitUI.framework */; }; + 7EE7C0222CB9E9D90000161D /* ResearchKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7EE7C01C2CB9E60E0000161D /* ResearchKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 7EE7C0172CB9E60E0000161D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = B183A5951A8535D100C76870; + remoteInfo = ResearchKit; + }; + 7EE7C0192CB9E60E0000161D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 86CC8E9A1AC09332001CCD89; + remoteInfo = ResearchKitTests; + }; + 7EE7C01B2CB9E60E0000161D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = CA1C7A5A288B0C68004DAB3A; + remoteInfo = "ResearchKitUI (iOS)"; + }; + 7EE7C01D2CB9E60E0000161D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = CAD08967289DD747007B2A98; + remoteInfo = ResearchKitActiveTask; + }; + 7EE7C0232CB9EC410000161D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = B183A4731A8535D100C76870; + remoteInfo = ResearchKit; + }; + 7EE7C0252CB9EC410000161D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = CA1C7A40288B0C68004DAB3A; + remoteInfo = "ResearchKitUI (iOS)"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 7EE7C0082CB8FF010000161D /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 7EE7C0222CB9E9D90000161D /* ResearchKitUI.framework in Embed Frameworks */, + 7EE7C0202CB9E9D90000161D /* ResearchKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 7EE7BF982CB8F25B0000161D /* RK-Setup-Git.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "RK-Setup-Git.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 7EE7BF9B2CB8F25B0000161D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -24,6 +89,8 @@ 7EE7BFA42CB8F25C0000161D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 7EE7BFA72CB8F25C0000161D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 7EE7BFA92CB8F25C0000161D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7EE7BFF52CB8FA1C0000161D /* SurveyTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurveyTask.swift; sourceTree = ""; }; + 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ResearchKit.xcodeproj; path = ResearchKit/ResearchKit.xcodeproj; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -31,6 +98,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7EE7C0212CB9E9D90000161D /* ResearchKitUI.framework in Frameworks */, + 7EE7C01F2CB9E9D90000161D /* ResearchKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -40,8 +109,10 @@ 7EE7BF8F2CB8F25B0000161D = { isa = PBXGroup; children = ( + 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */, 7EE7BF9A2CB8F25B0000161D /* RK-Setup-Git */, 7EE7BF992CB8F25B0000161D /* Products */, + 7EE7BFBE2CB8F7520000161D /* Frameworks */, ); sourceTree = ""; }; @@ -63,10 +134,29 @@ 7EE7BFA42CB8F25C0000161D /* Assets.xcassets */, 7EE7BFA62CB8F25C0000161D /* LaunchScreen.storyboard */, 7EE7BFA92CB8F25C0000161D /* Info.plist */, + 7EE7BFF52CB8FA1C0000161D /* SurveyTask.swift */, ); path = "RK-Setup-Git"; sourceTree = ""; }; + 7EE7BFBE2CB8F7520000161D /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + 7EE7C0112CB9E60E0000161D /* Products */ = { + isa = PBXGroup; + children = ( + 7EE7C0182CB9E60E0000161D /* ResearchKit.framework */, + 7EE7C01A2CB9E60E0000161D /* ResearchKitTests.xctest */, + 7EE7C01C2CB9E60E0000161D /* ResearchKitUI.framework */, + 7EE7C01E2CB9E60E0000161D /* ResearchKitActiveTask.framework */, + ); + name = Products; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -77,10 +167,13 @@ 7EE7BF942CB8F25B0000161D /* Sources */, 7EE7BF952CB8F25B0000161D /* Frameworks */, 7EE7BF962CB8F25B0000161D /* Resources */, + 7EE7C0082CB8FF010000161D /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( + 7EE7C0242CB9EC410000161D /* PBXTargetDependency */, + 7EE7C0262CB9EC410000161D /* PBXTargetDependency */, ); name = "RK-Setup-Git"; productName = "RK-Setup-Git"; @@ -113,6 +206,12 @@ mainGroup = 7EE7BF8F2CB8F25B0000161D; productRefGroup = 7EE7BF992CB8F25B0000161D /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 7EE7C0112CB9E60E0000161D /* Products */; + ProjectRef = 7EE7C0102CB9E60E0000161D /* ResearchKit.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 7EE7BF972CB8F25B0000161D /* RK-Setup-Git */, @@ -120,6 +219,37 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 7EE7C0182CB9E60E0000161D /* ResearchKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ResearchKit.framework; + remoteRef = 7EE7C0172CB9E60E0000161D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7EE7C01A2CB9E60E0000161D /* ResearchKitTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ResearchKitTests.xctest; + remoteRef = 7EE7C0192CB9E60E0000161D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7EE7C01C2CB9E60E0000161D /* ResearchKitUI.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ResearchKitUI.framework; + remoteRef = 7EE7C01B2CB9E60E0000161D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7EE7C01E2CB9E60E0000161D /* ResearchKitActiveTask.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ResearchKitActiveTask.framework; + remoteRef = 7EE7C01D2CB9E60E0000161D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 7EE7BF962CB8F25B0000161D /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -138,6 +268,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 7EE7BFF62CB8FA1C0000161D /* SurveyTask.swift in Sources */, 7EE7BFA02CB8F25B0000161D /* ViewController.swift in Sources */, 7EE7BF9C2CB8F25B0000161D /* AppDelegate.swift in Sources */, 7EE7BF9E2CB8F25B0000161D /* SceneDelegate.swift in Sources */, @@ -146,6 +277,19 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 7EE7C0242CB9EC410000161D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ResearchKit; + targetProxy = 7EE7C0232CB9EC410000161D /* PBXContainerItemProxy */; + }; + 7EE7C0262CB9EC410000161D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "ResearchKitUI (iOS)"; + targetProxy = 7EE7C0252CB9EC410000161D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 7EE7BFA12CB8F25B0000161D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -203,7 +347,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -266,7 +410,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; diff --git a/RK-Setup-Git.xcodeproj/xcuserdata/gmarx.xcuserdatad/xcschemes/xcschememanagement.plist b/RK-Setup-Git.xcodeproj/xcuserdata/gmarx.xcuserdatad/xcschemes/xcschememanagement.plist index cc23562..a5b5185 100644 --- a/RK-Setup-Git.xcodeproj/xcuserdata/gmarx.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/RK-Setup-Git.xcodeproj/xcuserdata/gmarx.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,7 +7,7 @@ RK-Setup-Git.xcscheme_^#shared#^_ orderHint - 0 + 3 diff --git a/RK-Setup-Git/Base.lproj/Main.storyboard b/RK-Setup-Git/Base.lproj/Main.storyboard index 25a7638..a2ecd72 100644 --- a/RK-Setup-Git/Base.lproj/Main.storyboard +++ b/RK-Setup-Git/Base.lproj/Main.storyboard @@ -1,24 +1,46 @@ - + + - + + - + - + - + + + + + + + + + + + + + diff --git a/RK-Setup-Git/SurveyTask.swift b/RK-Setup-Git/SurveyTask.swift new file mode 100644 index 0000000..9204fa6 --- /dev/null +++ b/RK-Setup-Git/SurveyTask.swift @@ -0,0 +1,27 @@ +// +// SurveyTask.swift +// RK-Setup-Git +// +// Created by Gerardo Marx Chávez Campos on 11/10/24. +// + +import ResearchKit + +struct SurveyTaskProvider { + + static func createHeightFormTask() -> ORKOrderedTask { + + let sectionHeaderFormItem = ORKFormItem(sectionTitle: "What's your height?") + let heightQuestionFormItem = ORKFormItem(identifier: "heightQuestionFormItem1", text: nil, answerFormat: ORKAnswerFormat.heightAnswerFormat()) + + heightQuestionFormItem.placeholder = "Tap here" + + let formStep = ORKFormStep(identifier: "HeighQuestionIdentifier", + title: "Height info", + text: "Please answer the questions") + + formStep.formItems = [sectionHeaderFormItem, heightQuestionFormItem] + + return ORKOrderedTask(identifier: "Survey Task", steps: [formStep]) + } +} diff --git a/RK-Setup-Git/ViewController.swift b/RK-Setup-Git/ViewController.swift index e48faa1..d00ee3a 100644 --- a/RK-Setup-Git/ViewController.swift +++ b/RK-Setup-Git/ViewController.swift @@ -6,14 +6,72 @@ // import UIKit +import ResearchKit +import ResearchKitUI -class ViewController: UIViewController { +class ViewController: UIViewController { + + @IBOutlet weak var startTapped: UIButton! + + @IBAction func startSurveyTapped(_ sender: Any) { + presentHeightSurvey() + } + override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. + startTapped.setTitle("Start Survey", for: .normal) } + + func presentHeightSurvey() { + let taskViewController = ORKTaskViewController(task: SurveyTaskProvider.createHeightFormTask(), taskRun: nil) + taskViewController.delegate = self + present(taskViewController, animated: true, completion: nil) + } +} +// Extesions can be in other file: +extension ViewController: ORKTaskViewControllerDelegate { + func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskFinishReason, error: (any Error)?) { + + // Handle the completion of the task and dismiss the view controller + taskViewController.dismiss(animated: true, completion: nil) + + //handle error + guard reason == .completed else { + if let error = error { + print("The task was not completed: \(error.localizedDescription)") + } + return + } + + // processing results: + if let results = taskViewController.result.results as? [ORKStepResult] { + processSurveyResults(results) + } + } + + private func processSurveyResults(_ results: [ORKStepResult]) { + // here + for stepResults in results { + for result in stepResults.results! { + if let questionResult = result as? ORKQuestionResult { + print("Question ID: \(questionResult.identifier)") + processQuestionResult(questionResult) + } + } + } + } + + + private func processQuestionResult(_ result: ORKQuestionResult) { + if let heightResult = result as? ORKNumericQuestionResult, result.identifier == "heightQuestionFormItem1" { + if let heigth = heightResult.numericAnswer { + print("User's heigth is: \(heigth) cm") + } + } + } + } - diff --git a/ResearchKit b/ResearchKit new file mode 160000 index 0000000..57427e8 --- /dev/null +++ b/ResearchKit @@ -0,0 +1 @@ +Subproject commit 57427e8c7e9c7c9e0186f99ebae22cfc6b5d51cb