医学调研常常是以给参与者填写一摞一摞的纸质问卷来进行的,当然还有电子问卷调查也是了解用户习惯的一个方法。但是开展这样的日常调查时非常令人乏味的,如果我们有更好的方法呢?
我们还有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项目。