Skip to content

Commit b3cff7d

Browse files
authored
Merge pull request #332 from erik-apple/update-readme
Update README with details about integrating ResearchKit
2 parents def63ce + f0c0592 commit b3cff7d

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ CareKit™ is an open source software framework for creating apps that help peop
3232
* [Schema](#schema)
3333
* [Scheduling](#scheduling)
3434
* [Custom Stores and Types](#custom-stores-and-types)
35+
* [Integrating with ResearchKit](#integrating-with-researchkit)
3536
* [Getting Help](#getting-help)
3637
* [License](#license)
3738

@@ -41,6 +42,7 @@ The primary CareKit framework codebase supports iOS and requires Xcode 11.0 or n
4142

4243
# Getting Started <a name="getting-started"></a>
4344

45+
* [Documentation](https://developer.apple.com/documentation/carekit)
4446
* WWDC Video: [ResearchKit and CareKit Reimagined](https://developer.apple.com/videos/play/wwdc2019/217/)
4547

4648
### Installation (Option One): SPM
@@ -498,10 +500,120 @@ your underlying data store to achieve greater performance or efficiency.
498500

499501
If you are considering implementing your own store, read over the protocol notes and documentation carefully.
500502

503+
# Integrating with ResearchKit <a name="integrating-with-researchkit"></a>
504+
505+
CareKit and ResearchKit are sister frameworks and are designed to integrate well with one another.
506+
507+
When integrating a ResearchKit into your CareKit app, there are a series of steps you will need to follow.
508+
509+
1. Subclass an existing task view controller
510+
2. Override the method that is called when the task is completed
511+
3. Present a ResearchKit survey and wait for the user to complete it
512+
4. Get the survey result and save it to CareKit's store
513+
514+
Here is an example demonstrating how to prompt the user to rate their pain on a scale of 1-10.
515+
Keep in mind as you're reading the code below that CareKit and ResearchKit both use the term "task", but that they are distinct.
516+
517+
518+
```swift
519+
// 1. Subclass a task view controller to customize the control flow and present a ResearchKit survey!
520+
class SurveyViewController: OCKInstructionsTaskViewController, ORKTaskViewControllerDelegate {
521+
522+
// 2. This method is called when the use taps the button!
523+
override func taskView(_ taskView: UIView & OCKTaskDisplayable, didCompleteEvent isComplete: Bool, at indexPath: IndexPath, sender: Any?) {
524+
525+
// 2a. If the task was marked incomplete, fall back on the super class's default behavior or deleting the outcome.
526+
if !isComplete {
527+
super.taskView(taskView, didCompleteEvent: isComplete, at: indexPath, sender: sender)
528+
return
529+
}
530+
531+
// 2b. If the user attempted to mark the task complete, display a ResearchKit survey.
532+
let answerFormat = ORKAnswerFormat.scale(withMaximumValue: 10, minimumValue: 1, defaultValue: 5, step: 1, vertical: false,
533+
maximumValueDescription: "Very painful", minimumValueDescription: "No pain")
534+
let painStep = ORKQuestionStep(identifier: "pain", title: "Pain Survey", question: "Rate your pain", answer: answerFormat)
535+
let surveyTask = ORKOrderedTask(identifier: "survey", steps: [painStep])
536+
let surveyViewController = ORKTaskViewController(task: surveyTask, taskRun: nil)
537+
surveyViewController.delegate = self
538+
539+
// 3a. Present the survey to the user
540+
present(surveyViewController, animated: true, completion: nil)
541+
}
542+
543+
// 3b. This method will be called when the user completes the survey.
544+
func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) {
545+
taskViewController.dismiss(animated: true, completion: nil)
546+
guard reason == .completed else {
547+
taskView.completionButton.isSelected = false
548+
return
549+
}
550+
551+
// 4a. Retrieve the result from the ResearchKit survey
552+
let survey = taskViewController.result.results!.first(where: { $0.identifier == "pain" }) as! ORKStepResult
553+
let painResult = survey.results!.first as! ORKScaleQuestionResult
554+
let answer = Int(truncating: painResult.scaleAnswer!)
555+
556+
// 4b. Save the result into CareKit's store
557+
controller.appendOutcomeValue(withType: answer, at: IndexPath(item: 0, section: 0), completion: nil)
558+
}
559+
}
560+
```
561+
562+
Once you have defined this view controller, you can add it into your app as you would any other CareKit view controller!
563+
564+
```swift
565+
let todaysSurveyCard = SurveyViewController(
566+
taskID: "survey",
567+
eventQuery: OCKEventQuery(for: Date()),
568+
storeManager: storeManager)
569+
570+
present(surveyCard, animated: true, completion: nil)
571+
```
572+
573+
You may also decide that you want the view to update to display the result of your survey instead of the default values used by the superclass. To change that, you can implement your own view synchronizer.
574+
575+
```swift
576+
class SurveyViewSynchronizer: OCKInstructionsTaskViewSynchronizer {
577+
578+
// Customize the initial state of the view
579+
override func makeView() -> OCKInstructionsTaskView {
580+
let instructionsView = super.makeView()
581+
instructionsView.completionButton.label.text = "Start Survey"
582+
return instructionsView
583+
}
584+
585+
// Customize how the view updates
586+
override func updateView(_ view: OCKInstructionsTaskView,
587+
context: OCKSynchronizationContext<OCKTaskEvents?>) {
588+
super.updateView(view, context: context)
589+
590+
// Check if an answer exists or not and set the detail label accordingly
591+
if let answer = context.viewModel?.firstEvent?.outcome?.values.first?.integerValue {
592+
view.headerView.detailLabel.text = "Pain Rating: \(answer)"
593+
} else {
594+
view.headerView.detailLabel.text = "Rate your pain on a scale of 1 to 10"
595+
}
596+
}
597+
}
598+
```
599+
600+
Now, when you create an instance of your `SurveyViewController`, you can pass in your custom view synchronizer to change how the view updates.
601+
602+
```swift
603+
let surveyCard = SurveyViewController(
604+
viewSynchronizer: SurveyViewSynchronizer(),
605+
taskID: "survey",
606+
eventQuery: OCKEventQuery(date: Date()),
607+
storeManager: storeManager)
608+
609+
present(surveyCard, animated: true, completion: nil)
610+
```
611+
501612
# Getting Help <a name="getting-help"></a>
502613

503614
GitHub is our primary forum for CareKit. Feel free to open up issues about questions, problems, or ideas.
504615

505616
# License <a name="license"></a>
506617

507618
This project is made available under the terms of a BSD license. See the [LICENSE](LICENSE) file.
619+

0 commit comments

Comments
 (0)