醫學調研常常是以給參與者填寫一摞一摞的紙質問卷來進行的,當然還有電子問卷調查也是了解用戶習慣的一個方法。但是開展這樣的日常調查時非常令人乏味的,如果我們有更好的方法呢?
我們還有ResearchKit(研究工具包)
ResearchKit,正如其名,是一個跟研究相關的東西。ResearchKit是一個由蘋果發行的開源框架,它主要是為了能讓哥蘋果的開發者開發專門召集病人參加醫學調研的醫學調查APP。這個框架有你開發一個醫學研究APP所需的所有東西。
用ResearchKit開發的醫學APP使得來自世界各地的參與者都可以參加調查。現今已存在幫助我們更好地了解諸如哮喘、帕金森、乳腺癌、糖尿病等等疾病現狀的APP。ResearchKit提供可以從設備傳感器收集數據的框架,但卻沒提供將已收集的數據上傳到服務器的方法。不僅如此,ResearchKit還可以和蘋果的HealthKit的框架無縫合作,使得從HealthKit收集像步伐計數和心跳數等等的數據變得更容易。
ResearchKit框架提供三個模塊:
許可-提供獲得參與者許可的基本機制
調查-促使用戶回答一系列問題
活動任務-指示參與者為調查目的進行一個特定的任務(如手指敲擊)。
在這個教程我們將對每個模塊進行細致的討論。還有我們將做個演示APP像您展示如何使用許可,調查以及活動任務模塊。
創建演示APP
這個演示的目的是創建一個簡單的APP。所以打開你的Xcode,用Single View Application模板創建一個新項目。將你的應用程序命名為SampleResearchKit,進入一個組織標識符,設置iPhone對該設備友好。把你的項目保存在某個地方並點擊創建。
使用CocoaPods是將ResearchKit裝入iOS項目的最簡單的方法。如果你已經安裝了CocoaPods,你可以按照如下步驟將ResearchKit文件庫裝入你的Xcode項目:
打開終端並執行如下指令在你的Xcode項目中創建一個名為Podfile的文件。
cd [your-projectPath] pod init cd [your-projectPath] pod init
當Podfile創建完成,編輯pod file並在文件中加入一行代碼 pod 'ResearchKit', '~> 1.0':
pod file # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' target 'SampleResearchKit' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! # Pods for SampleResearchKit pod 'ResearchKit', '~> 1.0' end
最後我們在終端中運行pod install。下載安裝ResearchKit文件庫,然後在Xcode中創建一個名為SampleResearchKit.xcworkspace的工作間。在Xcode中打開這個工作間。
在APP中添加UI
接下來讓我們來為APP設計UI。進入Main.storyboard,在視圖控制器中添加三個按鍵如下:
創建許可(consentClicked),調查(surveyClicked)和活動任務 (activeTaskClicked)動作按鍵。確保按鍵和action代碼之間的聯系,將action代碼命名如下:
Consent 按鍵– consentClicked
Survey 按鍵 – surveyClicked
Action Task 按鍵 – activeTaskClicked
在經過修改後,你的ViewController.swift應該像下面這樣:
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func consentClicked(sender : AnyObject) { } 11 @IBAction func surveyClicked(sender : AnyObject) { } 11 @IBAction func activeTaskClicked(sender : AnyObject) { } }
獲取許可
在調查時,研究著通常需要為他們的調查提交文件。如果是以人為主題的醫學調查,那麼調查可能涉及到一些敏感信息,所以就需要參與者進行審查。你需要確保在合法的形式下獲得了許可。ResearchKit為展示許可的文件以及獲得參與者簽名提供了更簡單的方法。
我們首先會看到如何在我們的示例項目中放入許可按鍵。讓我們先從創建一個空白的swift文件開始,將其命名為ConsentTask.swift。打開文件並把它輸入Researchkit框架:
import ResearchKit
在ConsentTask.swift中添加如下代碼:
public var ConsentTask: ORKOrderedTask { let Document = ORKConsentDocument() Document.title = "Test Consent" }
在這裡我們將創建一個ORKConsentDocument對象,這個對象將會被展示給參與者,裡面包含了關於調查的信息以獲取他的簽名。
ORKConsentDocument包含了可以被定義為ORKConsentSectionType的部分類型。ORKConsentSectionType列舉了在ResearchKit框架中預先定義的visual consent sections。我們可以用如下代碼進行添加,你可以根據調查需要添加section type。你可以移除不需要的section。在添加section types代碼如下之後:
public var ConsentTask: ORKOrderedTask { let Document = ORKConsentDocument() Document.title = "Test Consent" let sectionTypes: [ORKConsentSectionType] = [ .overview, .dataGathering, .privacy, .dataUse, .timeCommitment, .studySurvey, .studyTasks, .withdrawing ] let consentSections: [ORKConsentSection] = sectionTypes.map { contentSectionType in let consentSection = ORKConsentSection(type: contentSectionType) consentSection.summary = "Complete the study" consentSection.content = "This survey will ask you three questions and you will also measure your tapping speed by performing a small activity." return consentSection } }
ORKConsentSection分類展示了許可文件中的一個部分。在這裡我們將通過sectionTypes數組發送請求為一些特定的section type添加summary(總結)和content(內容)。我們將在沒一個部分都使用相同的summary(總結)和content(內容)。但是你可以根據section types進行設置。
現在我們要對我們的文件添加簽名。ResearchKit使得對文件添加簽名變得異常容易。繼續添如下代碼:
Document.sections = consentSections Document.addSignature(ORKConsentSignature(forPersonWithTitle: nil, dateFormatString: nil, identifier: "UserSignature"))
ORKConsentSignature分類代表了像ORKConsentDocument對象一樣的簽名。你也可以用一個名字、數據預先安裝簽名。這裡的標識符將在文件中作為一個特別實體來區分不同的簽名。
現在我們已經創建了一個文件。下一步就是為現在的任務准備步驟好讓我們可以展示給參與者。繼續輸入如下代碼:
var steps = [ORKStep]() //Visual Consent let visualConsentStep = ORKVisualConsentStep(identifier: "VisualConsent", document: Document) steps += [visualConsentStep] //Signature let signature = Document.signatures!.first! as ORKConsentSignature let reviewConsentStep = ORKConsentReviewStep(identifier: "Review", signature: signature, in: Document) reviewConsentStep.text = "Review the consent" reviewConsentStep.reasonForConsent = "Consent to join the Research Study." steps += [reviewConsentStep] //Completion let completionStep = ORKCompletionStep(identifier: "CompletionStep") completionStep.title = "Welcome" completionStep.text = "Thank you for joining this study." steps += [completionStep]
ORKStep展示的一個步驟可能是個問題,可能是一個活動測試,或者一個簡單的指示。由於我們將展示多個步驟,首先我們要創建一個ORKStep空數組。我們將添加三個任務:
視覺許可步驟(ORKVisualConsentStep)-ORKVisualConsentStep對象的作用是是用來展示幫助參與者理解許可文件內容的一系列細節。
許可審核步驟(ORKConsentReviewStep)- (ORKConsentReviewStep)對象的作用是展示供審核的許可文件。用戶將被要求輸入姓名並簽上他們的簽名。輸入姓名和簽名是非強制的。
完成步驟(ORKCompletionStep)-這個步驟將在審核任務完成後展示給用戶。
最後,在所有步驟結束後我們必須返回ORKOrderedTask對象。加入返回聲明如下:
return ORKOrderedTask(identifier: "ConsentTask", steps: steps)
如果你已經正確執行了上面的步驟,ConsentTask的最終代碼就是像下面這樣:
public var ConsentTask: ORKOrderedTask { let Document = ORKConsentDocument() Document.title = "Test Consent" let sectionTypes: [ORKConsentSectionType] = [ .overview, .dataGathering, .privacy, .dataUse, .timeCommitment, .studySurvey, .studyTasks, .withdrawing ] let consentSections: [ORKConsentSection] = sectionTypes.map { contentSectionType in let consentSection = ORKConsentSection(type: contentSectionType) consentSection.summary = "Complete the study" consentSection.content = "This survey will ask you three questions and you will also measure your tapping speed by performing a small activity." return consentSection } Document.sections = consentSections Document.addSignature(ORKConsentSignature(forPersonWithTitle: nil, dateFormatString: nil, identifier: "UserSignature")) var steps = [ORKStep]() //Visual Consent let visualConsentStep = ORKVisualConsentStep(identifier: "VisualConsent", document: Document) steps += [visualConsentStep] //Signature let signature = Document.signatures!.first! as ORKConsentSignature let reviewConsentStep = ORKConsentReviewStep(identifier: "Review", signature: signature, in: Document) reviewConsentStep.text = "Review the consent" reviewConsentStep.reasonForConsent = "Consent to join the Research Study." steps += [reviewConsentStep] //Completion let completionStep = ORKCompletionStep(identifier: "CompletionStep") completionStep.title = "Welcome" completionStep.text = "Thank you for joining this study." steps += [completionStep] return ORKOrderedTask(identifier: "ConsentTask", steps: steps) }
許可任務創建之後,是時候像用戶展示了。讓我們回到ViewController.Swift。首先,在文件開頭添加一個輸入聲明:
import ResearchKit
視圖控制器將負責處理許可的結果。所以采取ORKTaskViewControllerDelegate協議:
class ViewController: UIViewController, ORKTaskViewControllerDelegate {
當Consent按鍵被點擊時,我們將展示許可任務。因此執行onsentClicked代碼如下:
@IBAction func consentClicked(sender : AnyObject) { let taskViewController = ORKTaskViewController(task: ConsentTask, taskRun: nil) taskViewController.delegate = self present(taskViewController, animated: true, completion: nil) }
為了處理許可任務的結果,我麼將執行ORKTaskViewControllerDelegate協議的代碼如下:
func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { taskViewController.dismiss(animated: true, completion: nil) }
你可以通過獲取任務結果(taskViewController.result)提供特殊的處理。在這個演示中,我們將只是簡單地消除視圖控制器。
現在是時候運行APP來測試它的性能了。你將看到你用無與倫比的內置動畫添加進文件的所有部分。通過所有部分之後,你將看到審核頁面和視覺許可的頁面。你將被要求輸入姓名及簽上簽名以參加調查。
創建調查
調查不過是你用來收集參與者數據的一系列問題罷了。這裡有ResearchKit框架提供的兩類調查任務:
ORKOrderedTask -步驟順序一致的任務。
ORKNavigableOrderedTask-根據用戶如何在上一個步驟回答問題可以對步驟進行調整的任務。
現在我們將在我們的演示APP上創建一個調查。因此我們要創建一個空的swift文件,將其命名為SurveyTask.swift。在SurveyTask.swift中添加如下代碼:
import ResearchKit public var SurveyTask: ORKOrderedTask { var steps = [ORKStep]() return ORKOrderedTask(identifier: "SurveyTask", steps: steps) }
在這裡我們已經創建了一個任務,但是我們需要向這個任務添加問題。這個框架提供了一個給參與者提供任務指示的ORKInstructionStep分類。你可以通過指示步驟在任務中展示不用類型的內容。在這裡我們將創建一個能讓參與者知道調查目的
ORKInstructionStep對象。在var steps = [ORKStep]()之後添加如下代碼: //Introduction let instructionStep = ORKInstructionStep(identifier: "IntroStep") instructionStep.title = "Test Survey" instructionStep.text = "Answer three questions to complete the survey." steps += [instructionStep]
接下來,我們將像添加一個問題,這個問像有輸入類型一樣的文本答案:
//Text Input Question let nameAnswerFormat = ORKTextAnswerFormat(maximumLength: 20) nameAnswerFormat.multipleLines = false let nameQuestionStepTitle = "What is your name?" let nameQuestionStep = ORKQuestionStep(identifier: "NameStep", title: nameQuestionStepTitle, answer: nameAnswerFormat) steps += [nameQuestionStep]
ORKQuestionStep對象被用來向用戶提供單一的問題。在這裡我們像用戶發送請求,希望一個文本響應。所以我們創建一個和問題聯系的ORKTextAnswerFormat對象。這就是你為調查創建問題的方法。
我們將向我們的調查添加更多的問題。繼續添加如下代碼:
//Image Input Question let moodQuestion = "How do you feel today?" let moodImages = [ (UIImage(named: "Happy")!, "Happy"), (UIImage(named: "Angry")!, "Angry"), (UIImage(named: "Sad")!, "Sad"), ] let moodChoice : [ORKImageChoice] = moodImages.map { return ORKImageChoice(normalImage: $0.0, selectedImage: nil, text: $0.1, value: $0.1 as NSCoding & NSCopying & NSObjectProtocol) } let answerFormat: ORKImageChoiceAnswerFormat = ORKAnswerFormat.choiceAnswerFormat(with: moodChoice) let moodQuestionStep = ORKQuestionStep(identifier: "MoodStep", title: moodQuestion, answer: answerFormat) steps += [moodQuestionStep]
這次我們將只更改輸入的圖像添加另一個問題。我們問用戶“How do you feel today?”,然後向他們展示一組圖像作為答案。ORKImageChoice將被用來向用戶展示圖像。圖像選項通常將在一個水平線上進行展示。
接下來,我們將創建一個輸入數字的問題。
//Numeric Input Question let ageQuestion = "How old are you?" let ageAnswer = ORKNumericAnswerFormat.integerAnswerFormat(withUnit: "years") ageAnswer.minimum = 18 ageAnswer.maximum = 85 let ageQuestionStep = ORKQuestionStep(identifier: "AgeStep", title: ageQuestion, answer: ageAnswer) steps += [ageQuestionStep]
在這個問題中,我們要求用戶輸入他/她們的年齡。我們使用ORKNumericAnswerFormat將問題格式定義為數字。與此同時,我們要設置最大的和最小的年齡值。
既然我們現在已經定義了我們的問題,最後一步就是總結和說“謝謝”:
//Summary let completionStep = ORKCompletionStep(identifier: "SummaryStep") completionStep.title = "Thank You!!" completionStep.text = "You have completed the survey" steps += [completionStep]
以上就是我們的調查任務。是時候把調查展示給用戶了。讓我們返回ViewController.swift並更新surveyClicked代碼如下:
@IBAction func surveyClicked(sender : AnyObject) { let taskViewController = ORKTaskViewController(task: SurveyTask, taskRun: nil) taskViewController.delegate = self present(taskViewController, animated: true, completion: nil) }
你可以通過授權代碼對結果進行處理。但是在這個演示中,我們保持授權代碼不變,而只是消除任務控制器。在你測試APP之前,確保你已經下好了圖像文件,並且已經把他們添加進了Asset.xcassets。
現在我們來運行APP看看我們的調查長什麼樣。
活動任務
ResearchKit框架的最初目的只是為了調查者在用戶被邀請進行某個調查時從設備傳感器收集數據。活動任務可以請求用戶在使用像加速計,陀螺儀,GPS和觸摸的傳感器時進行數據收集。你可以邀請用戶走一定的距離然後用你的APP收集加速計數據。
ResearchKit框架包含了一系列的預先定義的活動任務,比如測試用戶的反應速度。在這個演示中,我們將創建一個觸摸任務要求用戶進行一些點擊。
首先,我們先創建一個空的swift文件。命名為ActiveTask.swift。將下面的代碼輸入ActiveTask.swift文件:
import ResearchKit public var ActiveTask: ORKOrderedTask { return ORKOrderedTask.twoFingerTappingIntervalTask(withIdentifier: "TapTask", intendedUseDescription: "Check tapping speed", duration: 6, handOptions: .both, options: ORKPredefinedTaskOption()) }
twoFingerTappingIntervalTask是預先定義的任務之一,它要求用戶對兩個屏幕上的目標進行快速而隨機的點擊。我們用它來添加一個點擊動作,並把標識符設置為“TapTask”。然後我們把“Check tapping speed”的持續時間描述為6秒。在這個任務中收集的數據包括觸摸活動和加速計信息。
就是這樣了。我們已經創建了一個活動任務。現在我們需要在ViewController.swift中激活這個任務並把activeTaskClicked代碼更新如下:
@IBAction func activeTaskClicked(sender : AnyObject) { let taskViewController = ORKTaskViewController(task: ActiveTask, taskRun: nil) taskViewController.delegate = self present(taskViewController, animated: true, completion: nil) }
現在是時候測試活動任務的特性了。創建並運行APP,點擊Active Task按鍵看看會發生什麼。
總結
在本教程中,我們已經講解了Researchkit框架的三個模塊。在這三個模塊中你可以創建非常優秀的調查APP而且具有無限的可能性。關於這個框架的更多詳情,你可以參考official ResearchKit documentation。
你可以從GitHub上參考完整的Xcode項目。