CareKit Tutorial for iOS: Part 1
In the first part of our CareKit Tutorial for iOS, you’ll learn the basics of using CareKit by building a Zombie Training and Symptom Tracker. By Jeff Rames.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Preparing Care Plan Data
Now you need to generate some care plan data, which will require a bit of setup. Select the Care Plan Store group in the Project Navigator and select File\New\File…, then choose the iOS\Source\Swift File template and click Next. Name the file CarePlanData.swift and click Create. In the new file, replace the template code with the following:
import CareKit
enum ActivityIdentifier: String {
case cardio
case limberUp = "Limber Up"
case targetPractice = "Target Practice"
case pulse
case temperature
}
class CarePlanData: NSObject {
let carePlanStore: OCKCarePlanStore
init(carePlanStore: OCKCarePlanStore) {
self.carePlanStore = carePlanStore
//TODO: Define intervention activities
//TODO: Define assessment activities
super.init()
//TODO: Add activities to store
}
}
This code creates an enum, ActivityIdentifier
, that will provide unique identifiers for intervention and assessment activities. It then defines a stubbed-out CarePlanData
class which will be tasked with defining activities and adding them to the data store. Its initializer currently grabs a reference to OCKCarePlanStore
for this purpose.
To initialize an OCKCarePlanActivity
to define an activity, you need to provide a schedule minimally defining a start date and frequency. Add the following to CarePlanData
just below the properties:
class func dailyScheduleRepeating(occurencesPerDay: UInt) -> OCKCareSchedule {
return OCKCareSchedule.dailySchedule(withStartDate: DateComponents.firstDateOfCurrentWeek,
occurrencesPerDay: occurencesPerDay)
}
This method calls the convenience initializer dailySchedule(withStartDate:occurrencesPerDay:)
, which creates an OCKCareSchedule
with the given start date and number of daily occurrences. For the start date, you’re using NSDateComponents.firstDateOfCurrentWeek
which is a computed property included with the starter project. This will generate results to cover the current week.
Intervention Activities
Now you’re ready to create some intervention activities. Replace //TODO: Define intervention activities
with:
let cardioActivity = OCKCarePlanActivity(
identifier: ActivityIdentifier.cardio.rawValue,
groupIdentifier: nil,
type: .intervention,
title: "Cardio",
text: "60 Minutes",
tintColor: UIColor.darkOrange(),
instructions: "Jog at a moderate pace for an hour. If there isn't an actual one, imagine a horde of zombies behind you.",
imageURL: nil,
schedule:CarePlanData.dailyScheduleRepeating(occurencesPerDay: 2),
resultResettable: true,
userInfo: nil)
let limberUpActivity = OCKCarePlanActivity(
identifier: ActivityIdentifier.limberUp.rawValue,
groupIdentifier: nil,
type: .intervention,
title: "Limber Up",
text: "Stretch Regularly",
tintColor: UIColor.darkOrange(),
instructions: "Stretch and warm up muscles in your arms, legs and back before any expected burst of activity. This is especially important if, for example, you're heading down a hill to inspect a Hostess truck.",
imageURL: nil,
schedule: CarePlanData.dailyScheduleRepeating(occurencesPerDay: 6),
resultResettable: true,
userInfo: nil)
let targetPracticeActivity = OCKCarePlanActivity(
identifier: ActivityIdentifier.targetPractice.rawValue,
groupIdentifier: nil,
type: .intervention,
title: "Target Practice",
text: nil,
tintColor: UIColor.darkOrange(),
instructions: "Gather some objects that frustrated you before the apocalypse, like printers and construction barriers. Keep your eyes sharp and your arm steady, and blow as many holes as you can in them for at least five minutes.",
imageURL: nil,
schedule: CarePlanData.dailyScheduleRepeating(occurencesPerDay: 2),
resultResettable: true,
userInfo: nil)
This code allocates three OCKCarePlanActivity
objects of type intervention
, which correlate to your Care Card. Each has a unique identifier based on your enum along with the title, instructions, tint color and schedule created with the helper. Soon you’ll be able to view where each of these fields map.
To get the activities to appear in your Care Card View Controller, add them to the store by adding the following method to the bottom of CarePlanData
:
func add(activity: OCKCarePlanActivity) {
// 1
carePlanStore.activity(forIdentifier: activity.identifier) {
[weak self] (success, fetchedActivity, error) in
guard success else { return }
guard let strongSelf = self else { return }
// 2
if let _ = fetchedActivity { return }
// 3
strongSelf.carePlanStore.add(activity, completion: { _ in })
}
}
What this code does:
-
You call
activity(forIdentifier:completion:)
to search the store for an activity with the given identifier. This is required to avoid inserting items with duplicate identifiers. - If the fetch is successful,
fetchedActivity
unwraps; since there’s nothing to add, you return. - If the identifier didn’t exist, you call
add(_:completion:)
on the store to add theactivity
to thecarePlanStore
.
Now you can use that code to add each of the activities you defined. Back in init(carePlanStore:)
, replace //TODO: Add activities to store
with:
for activity in [cardioActivity, limberUpActivity, targetPracticeActivity] {
add(activity: activity)
}
This iterates through the activities you defined and adds each one to the store.
You need to initialize this data class so the process to add data to the store will begin, so head over to TabBarViewController.swift and add the following property at the top of TabBarViewController
:
fileprivate let carePlanData: CarePlanData
Now add the following to init(coder:)
, before the call to super
:
carePlanData = CarePlanData(carePlanStore: carePlanStoreManager.store)
This kicks off the initialization you wrote for CarePlanData
that adds activities to the store.
Build and run—you’ve got yourself a zombie apocalypse training plan! Tap any bubble to fill it in, indicating you’ve completed one instance (or event) of the activity, and Care Completion updates accordingly. Tap elsewhere on the cell to see the instructions you provided for that activity.
After a modest amount of code, mostly to seed the data source, you now have a UI that displays and updates persisted Care Card data. That’s great news for your zombie-apocalypse users!
Symptom and Measurement Tracker
Now that your users have a plan to avoid infection, it’s time to tackle symptom tracking to monitor their zombie status.
While the Care Card tracks actions taken to improve or maintain a condition, the Symptom and Measurement Tracker monitors progress. For ZombieKit, that means checking for signs of infection—or (un)death.
In TabBarViewController.swift, add the following property to the others at the top of TabBarViewController
:
fileprivate var symptomTrackerViewController: OCKSymptomTrackerViewController? = nil
You’ll need a reference to the OCKSymptomTrackerViewController
, as it will be used throughout this class.
In createSymptomTrackerStack()
, replace:
let viewController = UIViewController()
with the following:
let viewController = OCKSymptomTrackerViewController(carePlanStore: carePlanStoreManager.store)
viewController.progressRingTintColor = UIColor.darkGreen()
symptomTrackerViewController = viewController
This initializes your OCKSymptomTrackerViewController
while providing its datasource, the Care Plan Store. You also set the progressRingTintColor
, which optionally colors the progress indicator. Finally, you store the reference in symptomTrackerViewController
for use elsewhere.
Build and run, and check out the Symptom Tracker tab. Similarly to the Care Card, you’ll see a weekly and detail progress indicator, currently set to 100% due to your lack of activities.