Streaming is available in most browsers,
and in the WWDC app.
ResearchKit and CareKit Reimagined
The ResearchKit and CareKit frameworks are the fastest route to delivering powerful native iOS apps for the research and patient care field. Learn about the newest audio and speech active-tasks, a completely redesigned user experience, and modular architecture designed to make it a breeze to create care plan apps for any use case.
- CareKit Open Source Website
- CareKit Repository
- ResearchKit Open Source Website
- ResearchKit Overview
- ResearchKit Repository
- Presentation Slides (PDF)
Hello, everyone, and welcome to the session ResearchKit and CareKit reimagined. My name is Srinath. And I'm an engineer on the Help Team. Now, we have a lot of topics that we want to cover today. So let's jump right into it by looking at the overall flow for today's session.
As always, we'll get started with community updates. We'll then talk about updates we have made to the ResearchKit framework. And then we have some really exciting news that we want to share about the CareKit framework.
Jumping into community updates, we wanted to highlight some apps that have been released or updated in the past year that leverage the ResearchKit and CareKit frameworks. One such example is the FocalView app, which was released by Novartis. And it focuses on running ophthalmic clinical trials on a digital platform.
The other notable example is the FDA MyStudies app.
Now, this app is the patient-facing part of a compliant platform that can be used for clinical trials or real-world evidence studies. The FDA went on to Open Source the MyStudies app for other organizations to rebrand, publish, and use.
Now this year, apart from talking about apps, we also wanted to talk about publications. Now for context, the ResearchKit and CareKit frameworks were announced roughly three to four years back. And we have reached a point where we are starting to see an influx of publications coming from studies that have been running for the past few years.
Most of these publications talk about how successful a mobile-based study design has been towards things like participant enrollment, the ability to recruit diverse participants from both a geographic and demographic standpoint, as well as the overall reduction in per-participant cost as more participants continue to enroll.
Now let's take a look at a few of these publications. The Pride Study talks about how successful they were in recruiting and engaging with a large number of underrepresented participants for clinical research.
The Healthy Pregnancy study talks about low attrition rates and how they were able to get their participants to fill out mobile-based surveys and questionnaires at a regular cadence.
The Personal Touch publication is interesting, because this publication went out in May 2019. And we got to know about it roughly a week back when one of the authors submitted a poll request on GitHub to contribute some of the active tasks that they had built to support this publication back into the framework so that the rest of the community can leverage that as well.
And on that note, all of our health frameworks -- ResearchKit, CareKit, and HealthKit -- were introduced to empower the developers to create some amazing research and care apps.
On top of that, we also have some really powerful devices that have sensors, starting with accelerometer and gyroscope, all the way to electrodes that allows your users to take an EKG reading.
And be continued to be amazed by the work that our community of developers, researchers, and health professionals are able to accomplish by leveraging our products and platforms.
But every year, we still receive a lot of emails asking about a variety of questions, like, "What is ResearchKit and CareKit? Or how do I create a research or a care app?" And we also received proposals from research institutions for device grant requests, which is why this year, we are currently working on a couple of initiatives. And right now, I just want to give a brief preview about these initiatives. The first one is an investigator's support program that we are piloting. We are currently developing this program. And this will be live later this year. Now, this will be a Limited Apple Watch Grant Program that will have a very simple and easy proposal submission process.
We will prioritize studies that advance science and help people to lead healthier lives by uniquely leveraging our ecosystem. The second initiative that we want to preview right now is a redesigned website. Now, this website will contain clear information for everyone who wants to learn more about the ResearchKit and CareKit frameworks. You will also be able to gather insights from other researchers and developers who are leveraging these frameworks to build some amazing research and care apps. This website will also have a lot more information about the investigator support program. And both the website and the investigator support program itself will be live in Fall of 2019. And we are really excited about this.
And now, let's switch gears and talk about updates that we have made to the ResearchKit framework. We want to cover two main topics, UI updates, and active tasks.
Let's get started with UI updates. This year, our main focus has been around refining the user experience, around answering survey questionnaires. Because we realized that some of the validated medical questionnaires and onboarding flows can be extremely long.
So you can see here that we have updated the card styling for you to provide more contextual information to your users. This includes an intra step progress indicator, as well as a Learn More button. Now this button can be used for situations where your questions or answer choices contain terminologies but just not quite self-explanatory. So in this example, if your users are unaware of what narcolepsy actually means, they can simply tap on the Learn More button to pull up a sheet that gives them a lot of information about the question and the answer choices themselves. Now you'll notice that we have added a Top Content Image view. And this styling will now be consistent throughout ResearchKit, so all of our steps now have the ability to display rich media content via the Top Content image view. And if you scroll further down, we have added a new object of type body items, which can be used to compose lists that will be automatically formatted for you. And now let's take a look at how you can incorporate these changes into your existing apps.
So the first thing that you want to do is create an instance of ORK learnMoreStep with a unique identifier. All of our steps now have this image property, which will display as the top content image view. You can also customize other properties, like title and text.
The other thing that you need to do is create an instance of ORKBodyItem. And it accepts the following parameters, like text, detailed text, and a style. You can choose between bullet point images and just plain text. Now all of our steps accept an array of body items. So let's assign this body item to the learnMoreStep.
The next thing that you would want to do is create an instance of learnMoreItem and bypassing in the step. So this is the object that essentially creates the Detail Disclosure button on the screen. We also have another initializer which accepts text. So that one will be displayed as a hyperlink in your step.
We have also added another initializer to ORK form items in order to help you customize the section headers, which allows you to group multiple form items under the same section. Now this accepts properties like sectionTitle, detailText, the learnMoreItem, and the toggle to indicate whether or not you want to display the intra step progress indicator.
And now that you have incorporated these changes into your apps, your users can make an informed decision before answering any of your questions.
Now let's move on to active tasks. Now similar to last year, this year, we will be focusing on our three main areas of health -- vision, hearing, and speech.
Now when it comes to measuring visual health, there are two key metrics that are considered as the gold standard, visual acuity and contrast sensitivity.
Visual acuity is essentially your ability to distinguish and identify an object along with its features.
It comes in two stimulis. One is the Landolt C, and the other one is a Snellen or Tumbling E. Now our first active task in the visual acuity space is a contribution by Novartis from their FocalView app.
Now, this app essentially requests the user to align the outer dial with the opening in the letter C.
Now the Landolt C stimuli remains in fixed contrast but keeps decreasing in size and pops up in random orientations. Once a user completes this task, the developer will receive a visual acuity rating score for that user.
To incorporate this in your app, you create an instance of ORKLandoltCStep with a unique identifier. You then set the testType to be acuity. And then as always, you can create an ordered task by passing in an array of steps, then pass the task to create a TaskViewController, which you can present within your app.
Our second active task in the visual acuity space leverages Tumbling E as the stimuli. Now as part of this task, the user will be expected to swipe into the direction of the arms of the letter E.
Now similar to Landolt C, the Tumbling E will remain fixed in contrast, will decrease in size, and pop up in random orientation. But the interesting piece here is that the testing distance, along with the size of the stimuli, is controlled by the TrueDepth camera. And once the user completes this task, you will receive a lot more value, where MAR stands for Minimum Angle of Resolution.
To incorporate this in your app, you create an instance of ORKTumblingEStep with a unique identifier. You can also specify the minimum and maximum viewing distance that is specific to your trial. And same as always, you create an OrderedTask, pass that to the ViewController, and present it.
Now let's move on to our next big category ambition, contrast sensitivity. This essentially refers to your ability to distinguish an object from its background. And it comes in -- so two stimuli is most commonly used to test for this particular contrast sensitivity feature. One is Landolt C, and the other one is a Gabor Patch.
The first active task in contrast sensitivity is once again a contribution by Novartis from their FocalView app. Now, this is very much in line with the visual acuity task. But the key difference here is that the Landolt C remains fixed in size but keeps decreasing in contrast as it is being presented in random orientations.
And once the user completes this task, you will receive the visual acuity rating score for the user.
Adding this to your app is exactly the same as the visual acuity task. The only key difference is that you're going to toggle the test type to be contrast sensitivity.
As part of our next task, we will try to generate the contrast sensitivity function for a user by presenting them with the stimuli known as the Gabor Patch. And this is what it looks like. So you'll notice that there are certain lines on the stimuli that is leaning to the right, especially the top tilt. And in the other stimuli, you will notice that the top tilt, or the upward tilt, is leaning to the left. Now, your users will be expected to recognize that leaning of the tilt and select the appropriate direction as part of the task.
Now, the Gabor Patch stimuli is generated programmatically using an adaptive algorithm that varies the spatial frequency.
Now the Gabor Patch will be displayed with random orientations and different positions within the screen.
And once again, the testing distance and the size of the stimuli itself is controlled real time by the TrueDepth camera.
Once the user completes this task, the developer will be able to use the results to generate a sensitivity vs spatial frequency curve for the user.
To incorporate this in your app, you create an instance of ORKCSFStep with a unique identifier. Once again, you can set the minimum and maximum viewing distance that is specific to your trial.
You create an OrderedTask, pass that to the TaskViewController, and simply present it within your app.
Now the contrast sensitivity function and the Tumbling E active task that leverage the TrueDepth camera will be available soon via an Apple sample code license on developer.apple.com.
Now let's move on to our next category, hearing. So last year, we announced three new active tasks that focus on hearing health. We had to tone audiometry, speech and noise, and SPL meter.
This year, we are making across-the-board enhancements to the algorithms. And what's even better is that you can now write the results of these active tasks directly into HealthKit.
To learn more about these new data types, I would recommend you to check out the HealthKit session that's happening today at 2:00 p.m.
Now let's move on to speech. Last year, we introduced a speech recognition active task. When a user completes this task, you will receive a bunch of information, including the raw audio file, the transcript, as well as an SFTranscription object rendered by the speech recognition framework. Well, this year, the Speech Recognition team has added more capabilities to the SF transcription object. So you will be able to extract information like speaking rate and average pause duration. And on top of that, there's also a new object called SFVoiceAnalytics. And to learn more about these, please check out the session titled "Advances in Speech Recognition." And those were our overall updates and additions to our expanding library of active tasks.
Now, you might have noticed that some of these tasks leverage some system frameworks under the hood.
And we want to remind you that there are a lot of other powerful iOS system frameworks as part of our SDK. And we would highly encourage developers to leverage the true potential of these frameworks as you're thinking about adding new active tasks into ResearchKit or even if you are considering adding novel experiences that focus on health.
And with that, let's move on to updates for CareKit.
Now, the CareKit framework was introduced back in 2016 as an Open Source framework. And we wanted to enable the developers to perform three main things -- the ability to be able to easily digitize a prescription, the ability to provide meaningful data and trends to the user, and to allow your users to easily connect with their care providers.
And over the past few years, we've been making incremental updates to the framework. And this year, I'm really excited to announce CareKit 2.0. And this is what it looks like. Now you'll see that we have completely revamped the UI for the framework.
But what's even better is that we have fundamentally rearchitected and rewritten the framework purely using Swift.
Now, that means that CareKit, under the hood, can leverage some of the most powerful Swift language features, including the newly announced combined framework.
Now let's dive into some details. The CareKit framework now comprises of two other frameworks under the hood -- CareKit UI and CareKit Store.
CareKit UI is a separate project inside the CareKit repository that you can independently compile and expose as a separate framework.
CareKit UI is all about pre-packaged sub classes of UI views. So what that essentially means is that every single view that you see on the screen is available for you to leverage in your app using CareKit UI. And we have categorized them into three categories or components. We call them tasks, charts, and contacts. And these are used to reflect the functionality that each view is supposed to serve. Now, as I mentioned, all of the views in CareKit UI are just naive UI views and are essentially sub classes of UI views.
So I want to start off by talking about all the views that are available in tasks. And there are five of them that we want to highlight today.
Now here, you can see that we have a view. And since it is just a subclass of a UI view, you can constrain it anywhere within your app by adding it as a sub view.
Now to create this view, all you have to do is import CareKit UI, create an instance of OCKSimpleTaskView, and set some of the parameters that are available on this object.
It's that easy. And now let's take a look at the remaining four UIs that we said are available inside the task's component.
The next one that we want to cover is the OCKInstructionsTaskView. So when you create an object of this type, you will get a view that looks somewhat like this. And all you have to do is add one additional parameter to set the right values.
Along those same lines, the next view that we want to talk about is the OCKGridTaskView, which looks somewhat like this. Now this view is interesting because all the check marks and the buttons that you're seeing here, this is standard for a medication view. And as part of this view, we are essentially exposing the collectionView to you directly. So you could choose to set yourself up as the delegate and pass in whatever view you want into the collectionView. So you can choose to use an OCK button. Or you can even provide any custom UI. It is extremely customizable as well.
Our next view type is an OCKChecklistTaskView, which looks somewhat like this.
And all the buttons that you see on screen are now composed inside a Stack View. So by simply calling an appendItem method, you'll be able to add a new role into your checklist as a new item. Our final view type under the tasks component is an OCKSimpleLogTaskView. It looks somewhat like this. And it can be used for logging random events like a headache or nausea. And every time the user taps on the log button, we will show them a timestamp of when they logged their last event. And the timestamps are once again composed inside the stack view. So by simply calling the appendItem method, you'll be able to append more logs based on the action that is generated by the button. Now, let's move on to our next component, charts. So to create a chart in CareKit UI, you simply import CareKit UI. You create an instance of OCKCartesianChartCardView and specify a type. You can then go on to set the title, the text, and even the values as part of the data series. And by simply toggling the type, you'll be able to easily switch between the different chart types for that exact same set of data points.
And our final component which we want to cover today is contacts. So you can create an instance of OCKContactCardView and just populate it with content. And we will ensure that all the constraints are applied in the right way.
So those were our overall updates for CareKit UI. Our real intention here is to continue to add more views to each of these components and also expand the library of components that we have.
We think that this can be an extremely powerful tool for users and makes the CareKit 2.0 framework highly customizable, because we just give you all the new sorts of views with all the constraints taken care of.
Now let's talk about CareKit Store. CareKit Store, similar to CareKit UI, is its own project inside the CareKit framework.
So you can compile it and export it as a standalone framework into your app and use it in a completely unrelated manner. CareKit Store is essentially a wrapper on top of Core Data that allows you to persist Care Plans and react to them locally on device within your app containers. And since it's a database essentially, we have given you a cookie cutter scheme. And let's take a look at what that looks like. So the most fundamental entity for any Care app is the patient. Now let's take a look at how you initialize a CareKit Store, create a patient object, and ingest that into the CareKit Store.
So you start off by importing CareKitStore as a standalone framework. You then create an instance of OCKStore with a unique identifier to create the Core Data database within your app container. You then go on to create a patient object by using one of our convenience initializers that accepts some basic parameters.
You can then call the addPatientMethod on the Store, which asynchronously accepts the object and ingests it into the database.
And once that is complete, you will get a completion callback. And this will return a Swift result type that you can switch on.
Now our second key entity in our Care Plan is the Care Plan itself. And every patient can have multiple Care Plans associated with them. So now let's take a look at how you can create a new Care Plan and associate it with a particular patient.
So as always, you create a reference to the store. Now one thing to note here is that if you provide an identifier that is already available, we will just take an existing store with that identifier and return that to you.
So then, if you don't have a reference to the patient object, the first thing that you need to do is query the patient object from the Store.
And once that query completes asynchronously, you get a callback. And inside the callback, you can go on to create a Care Plan by providing it parameters like identifier, the name for the Care Plan, and most importantly, the patient ID. Doing this will essentially help create the association between the patient -- the Care Plan and the patient itself. And then you can call the addCarePlan method to ingest this new Care Plan into your database. Now every Care Plan can have an array of contacts associated with them. Now, these could be contacts for the primary care providers who are associated with this particular Care Plan. Now, the other thing that's interesting here is the notion of tasks. Now task entities are essentially action items that your users are requested to perform on a daily basis as part of their Care Plan. And every task has an associated schedule object with it. Now the schedule dictates when the user is expected to perform a particular task. So now let's take a look at how you can prescribe a particular medication to your user and ingest that into your Care Store.
So here, we are creating a schedule where you need to take your medication every day at 7:00 a.m. We are creating another schedule element that expects you to take the same medication every other day at 12:00 p.m. So we are calling the former one as breakfast dose and the latter one as the lunch dose. And you can simply compose multiple schedules together to create one unified schedule which you can then pass on to the task.
So the OCKTaskObject accepts parameters like identifier. The title here is a Doxylamine medication, and you can give it the schedule object. And you can directly add this task into your CareKit Store. Now, every time your user completes a particular task, we generate an outcome. And every outcome has an associated value with it.
Now let's take a look at how you can query all the outcomes in your database to create meaningful data and trends that you can surface to your users.
So here we are creating a blanket query that will query all elements in your database for the past seven days.
We are then calling the fetchInsights method on the task. And we are passing it the identifier for the particular tasks whose event you are interested in. So in this case, I'm only interested in events generated for the doxylamine medication task.
Now, this API has two blocks that are very interesting. The first one is the daily aggregator block which can be called multiple times. And every time, you get an array of events for that particular day. And you can use this to compute higher-order metrics.
And then you get the completion block, which is called only once. And it gives you an array of computed values that you can use for further analysis or simply for charting.
Now, every single entity in the CareKit Store can have an associated note object with it. Now note objects are essentially metadata. So for example, if the care provider decided to update the Care Plan for some reason, and they wanted to provide you with free form text, you will be able to add that to the note object.
And the other interesting thing is that some of our key entities are now versionable.
So when you update a medication task, or when you update a schedule, we will persist that in the CareKit Store and you can go back and forth between them. So those were our quick updates for the CareKit Store. There are a lot more powerful API's that are available in the CareKit Store framework. And we would recommend you to check them out.
So now let's turn our focus to the CareKit framework itself. CareKit is all about bringing synchronization all the way from the UI level to the underlying database. And the way we accomplish this is by using a synchronizer object. Now this object makes heavy use of the combined framework under the hood to propagate events between the UI layer and the data store layer.
Now, another key functionality of CareKit is its modularity and customizability. So what I mean by that is that the database here can either be a CareKit Store, or it can be any database of your preference, as long as it conforms to our OCKStore protocol, which will enable the synchronizer to interact with it seamlessly.
And the UI elements that you see here can either come from CareKit UI. Or they could be even your custom UI views, as long as you tell us how to bind the views to a particular object.
So now let's take a look at what happens when a user interacts with the UI element on the screen. So for this example, let's focus on the doxylamine medication on the top-left corner.
When the user taps on this button, an event is propagated to the synchronizer.
The synchronizer then forwards the information to the underlying data store. And once the database acknowledges successful receipt of this object, the synchronizer takes up the role of a publisher. And it propagates the stream to all the UI elements that are subscribed to that particular stream. And in this example, there are only three cards that are subscribed to updates from the medication task.
And once the stream reaches them, they will be able to independently update themselves.
This is really exciting because the UI views are acting independently of each other. And they're also updating in an asynchronous manner, which can lead to some really powerful experiences in your care app.
Now, let's take a look at how you can incorporate CareKit in your app end-to-end in code. So the first thing you do is you import CareKit. And doing so will automatically import the CareKit UI and CareKit Store frameworks.
Next, as always, you create an instance of OKCStore. And then you go on to create an instance of OCKSynchronizedStoreManager and pass it the store. This will allow the synchronizer to wrap itself around the database.
And finally, you can choose to use one of our prepackaged standalone view controllers. In this example, we are showcasing the OCKTaskListView controller and it accepts the storeManager assets parameter.
Doing this will essentially establish pipelines all the way from the UI layer to the underlying database, and all you have to do after that is present the view controller, and depending on what data you provide to the store, you'll be able to see a UI that looks somewhat like this.
And similarly, you can also leverage some of our other prepackaged view controllers to build out views for trends and contacts.
So as you can see here, CareKit 2.0 makes it really easy to use the framework.
But that's not all it's all about. So, right now, I want to call Erik onstage for a demo where we will showcase how you can build a custom care app using CareKit 2.0.
All right. Great. Thank you, Srinath.
Good afternoon, everybody. My name is Erik. I'm an engineer on the CareKit team. And today I have the privilege of walking y'all through a sample app that's going to demonstrate some of the amazing new features and capabilities of CareKit 2.0. The app that we're going to build to that -- together today is going to be built completely from scratch. And it's going to be for an imaginary patient, an expecting mother who is experiencing severe symptoms of morning sickness, namely nausea. So the app that we're going to make for her is going to allow her to track her medications. It's going to allow her to leave a log when she feels nauseous. And we're going to display charts to her that allow her to understand the correlation between her adherence and her symptoms. Finally, we're going to give her quick access to her contacts so that she can get directions to the office or make a call to her doctor if she has an emergency. Now, when we make a CareKit app, there's two major steps that we have to walk through. The first is that we need to create the Store. And we need to populate it with data. So that's going to be the first thing we tackle. And then after that, we need to create the UI and tell CareKit how we want the data to be displayed. So we're going to hit that in the second half.
Let's jump in.
All right. So you can see here, we've got an empty app. This is going to be our starting point. Now when you're using CareKit, the first thing you need to do is import it. If you don't do this, you're not going to get far. Once it's imported, the next thing we need to do is create the Store. More precisely, the SynchronizedStoreManager that's going to perform synchronization for us. Now when we do this, we're going to start off by creating the OCKStore. And then we're going to pass that into the SynchronizedStoreManager.
I want to pause here for a second and highlight something really important about CareKit 2.0.
Here, we're using the OCKStore, which is our wrapper on top of Core Data. But the OCKSynchronizedStoreManager can interface with any object that implements our OCKStore protocol. That means it would be possible for you to wrap a web server, a third-party database, or even a simple JSON file, and use that as your database. For our purposes today, we're going to stick with Core Data.
The next thing we need to do is populate some data in the Store. So we're just going to write a handy extension to take care of that for us. In a real situation, you may pull it down from a web server or load it in from your app bundle. But today, we're just going to code it up right in here. Now we're going to create two tasks, one to take a medication and one to check -- or one to log when you're feeling nauseous. So to do that, we're going to need to create a schedule.
We're creating a couple of dates. Don't worry too much about these. The important part is down here where we're creating the schedule. And we create that schedule by composing elements. We've got a breakfast element that repeats every day. So every day, we're going to take our medication at breakfast. Another one every day at lunch. And a third one every other day at dinner. You probably wouldn't actually schedule medication like this. But CareKit lets us make some really flexible scheduling. And we just wanted to show that off a little bit. With the schedule in hand, we can now create our task.
To do that, we need to specify a unique identifier. We're going to use doxylamine. This is a common medication prescribed for nausea.
And we'll tack on the schedule, of course. And we'll provide some instruction so that our imaginary patient knows exactly what to do.
Let's create one more task, this one for nausea. So in this case, we're going to create a more simple schedule. This schedule is going to run every day, all day. Because there is not any particular time that you might feel nauseous, we want you to be able to log any time. Finally, we'll create the task for it very much the same way as we did before. The key difference here is that we're saying that this task's impact adherence property is false.
You'll note at the top of most CareKit apps, you'll see a bunch of -- like a weekly calendar with some completion rings in it.
By setting this flag false, we'll exclude this nausea task from impacting those completion rings.
Now that we have our two task objects, we need to add them into the Store.
Pretty straightforward. And we've made it this far. So we've got our medication task, and we've got our nausea task. We also want to add in a couple of contacts so that our patient has somebody that they can contact if they need help. Contacts are created very much the same way as other CareKit entities. You have to give them a unique identifier. And you can set a number of properties on them. In this case, we'll set an image, a title, and a role. And then we can also provide contact information for them.
Here, we'll give them an email address, a phone number, and a message. Finally, we're going to tack on an address. And this address will allow our patient to get directions from Maps if they need to get into the office.
We'll add one more contact, very much the same way as the first.
Finally, we're going to add both contacts into the Store.
All right, so we've got our two tasks in the Store. We've got our two contacts in the Store. That brings us to the end of the first step. We've made it through creating a Store. And we've made it through adding our data into the Store. That means the second step is to generate the UI. We have to write the code to tell CareKit how we would like this displayed. And the way that we're going to do that is to write a ViewController. So here, we're creating our careViewController. We're going to go into this in just a second. But you'll note that I'm passing in the storeManager. This is going to be used for synchronization.
Finally, we'll set this ViewController as our root view, so that when we run the app, this is where we're going to start. Let's jump in here and see what we have. This is presently an empty class. You can see that inherits from OCKDailyPageViewController. If you're creating a CareKit app, and you want some serious customization power, OCKDailyPageViewController is a really good starting point.
When you inherit from this class, what you're going to get is a viewController that has the calendar up at the top with the completion rings in it. And the user will be able to page through that and select the date that they like. And down below that, you'll have a second pageViewController. And each time, the user changes the date either by swiping or tapping, you're going to get a callback.
This callback, as a matter of fact. And inside of this function, you're going to receive these two parameters, a listViewController and the date. The date is the date that the user has just selected. And the listViewController is an empty page of content. And as the developer, your job is to fill in the content that you'd like the user to see for the date they selected. And doing that is very straightforward.
Here, we're creating an OCKChecklistTaskViewController. And we can append that onto the listViewController. That will add it into the content for the selected day.
So let's take a quick look at this class, the OCKChecklistTaskViewController. Now you'll note from Srinath's just -- talk just a moment ago that there's CareKit UI and CareKit. And in CareKit UI, we had the tasks views. And there were four or five of them. Well, in CareKit, there's parity. And there's a matching view controller for each of those.
The key difference is that the views in CareKit UI are naive and not synchronized, whereas the view controllers in CareKit will update automatically.
When we instantiate this, we need to pass it the Store. And we need to tell it which task we'd like it to display the data for.
Finally, we give it an event query that specifies that it should only show the events for today.
So this is our medication card. It's going to ask the patient to take their doxylamine. We'll add one more.
SimpleLogTaskViewController takes the exact same arguments. And this one is going to ask the user to log when they're feeling nauseous.
We've written a lot of code. But we're finally ready to run the app and see what it looks like.
All right, so we're up and running. This is what we have so far. You can see we've got both of the tasks that we've added.
The user can swipe through the dates on the calendar.
They can get back to today like this.
You'll also note that on some days, we have two events. On other days, we have three events. That's due to the way that we scheduled our task.
And when the user checks off a task, the completion rings fill up automatically.
This synchronization between the tasks, the TaskViewController, and the CalendarViewController up at the top happens automatically through the Store synchronizer.
You'll also note that when we log nausea events, they don't show up in the completion ring because we explicitly marked those impacts adherence equals false when we created our task.
Now before we move on, I want to hit on two places where we can really easily customize our CareKit app. And I think you guys will really like these.
The first one, if we have -- hope back to our app delegate is that we can set a tint color on the window. And this tint color will propagate down through our entire app. And it's a really easy way to apply styling or to brand your app.
The second one is to switch out the kind of task view that we're using. So you remember that there were a number of different views for tasks in CareKit UI.
And we can switch to a different one simply by switching the ViewController we're using. They all have the same initializers.
We'll rerun our app and take a look at how this changes it.
Awesome. So you can see the color is different now. And we also have an entirely different task card to look at. Now, what's really interesting about this card is that it shows the time that the user is supposed to take their medication. But when we check one of these off, the time that it displays changes to the moment that the user tapped the button. This is really useful because it allows our patient to see the last time that she's taken her medication.
All right. I think we're ready to move on to creating some charts now. I think what we'll do is try to put a chart right in between the two cards that we have. Maybe we'll make it a bar chart. And we'll say that it will show the number of times our patient is taking their medication versus the number of times that she's felt nauseous.
So we'll drop down right here between the two cards that we've created already. And we're going to need to create two data series, one for the medication, and one for the nausea. So we're going to start with the nausea one. When we create this data series, we have to give it the identifier. This is a task whose data we'd like to display. We can give it a legend title, a pair of colors to plot in, and a marker size, which in this case will dictate the width of the bar chart. And an event aggregator. The event aggregator determines the y-axis value. And in this case, we're simply going to count the number of times that our patient has felt nauseous.
We'll do this once more, this time for our medication.
And it's going to be very much the same.
With both of these in hand, we can create an OCKCartesianChartViewController. The initializer takes the storeManager. Again, this is to provide that synchronization that makes CareKit so great. And we also pass in a data series, one for each series that we'd like displayed on the chart.
We also pass in the date that we'd like the data displayed for and the plot type. Here, we're going to use the bar chart. But you could just as easily use the scatter plot or the line plot.
Finally, before we run our app again, we're going to set a couple of labels so that our patient can understand the data that we're displaying to her. Let's run it one more time and take a look at our chart.
Awesome. So you can see down here we've got our chart. It's got data shown on it. But what's really fantastic about this chart is that it updates in real time with beautiful animations as we check off data.
Perhaps on the first day, our user didn't take her medication.
And she felt really sick.
On the second day, she started to take it. So she felt a little bit better. And on the third day, she took all of her medication. And today, she also took all of it and doesn't feel sick at all.
So you can see we're already getting a pretty good patient experience. But there's another feature that we can take advantage of that I think you guys will really like.
CareKit now has the ability to add arbitrary content anywhere in this listViewController. Let me show you how we can do that.
So up at the very top, I think we'd like to add a banner.
And we're going to do that by creating this tipView. We'll set some text on the tipView. And we'll also attach an image to it. But what's really important here is that we simply append it as a view.
Now what I want you to note is that this tipView is not part of CareKit. We created it just for this demo. And it could just as easily be a view that came from your application or a third-party library.
When we run our app now, you'll see that we get this beautiful banner up at the top that encourages our patient to learn more about the relationship between exercise and healthy pregnancy. You can imagine that there is a plethora of ways that this could be used. You could populate this data based on what's already in your patient's Care Plan Store. You could pull it down from a server. Or you could set it based on the date. The possibilities are really endless here.
Now the last thing that I want to do before we wrap up our demo is give our user quick access to her contacts. And I think what we'll do is just add a Care Team button up here that shows a modal presentation with all her contacts in it. And CareKit makes that really easy. Up at the top, we're going to create our UI Bar Button item. And we're going to set it to call this function here, in which we're going to create an instance of the OCKContactsListViewController. This is a really handy class that we provide for you. All you need to do is pass it a Store manager. And it will automatically query all the contacts in your Store and display them for you.
Run our app one last time to see what it looks like.
There we go. So we'll tap on this and out come our contacts. Now, if our patient needs directions into the office, she's just a tap away from Maps. It looks like it's about 4.9 miles.
That's not too shabby. All right. So we've got our contacts in there. And our app is looking pretty good. I think I'd like to wind down the demo right here. Let's call this complete. But before we go back to Srinath, I want to just reflect for a moment on what we've done.
In what accounts for about 15 minutes and more or less 200 lines of code, we've been able to complete a beautiful patient care application with gorgeous animations.
But what's most important about this application is that it's extremely modular. None of the views know about each other.
All of the viewControllers are completely decoupled. No delegates are set that tie things together. This app can be very easily updated and changed as the needs of our users evolve. We think the possibility for CareKit 2.0 is boundless. And we are really excited to see all the amazing things that our developers are going to do with it.
All right. Back to you, Srinath.
Wow, thank you, Erik, for that great demo. So now to just summarize the whole session, CareKit is just a fundamental rewrite and rearchitecture of the framework. It still holds on to its core values. But now it makes it extremely powerful to use, to build like really amazing Care app experiences for your user. So we spoke about ResearchKit, where we talked about UI updates that we've made throughout the framework, as well as new additions to our existing library of active tasks. And finally, we also touched upon all the updates from our community, including our two key initiatives -- the investigator support program, and our redesigned website that's coming this fall.
And as always, ResearchKit and CareKit are Open Source frameworks. That's available right now on GitHub.
Now over the next few months, we're going to be working really hard to add a lot more capabilities to these frameworks. We'll be adding support for Dark Mode. We'll be adding accessibility, localization, as well as more documentation support as well. And we would highly encourage all the developers in our community to provide us with feedback as well as contribute as we continue to evolve and expand our amazing frameworks.
For more information about the session, please visit this link. We are also holding a ResearchKit and CareKit lab tomorrow at noon where all of us will be there to answer any questions that you have. And with that, thank you all for coming. And have a great WWDC. [ Cheering and Applause ]
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.