Giter Site home page Giter Site logo

carekit-apple / carekit Goto Github PK

View Code? Open in Web Editor NEW
2.4K 143.0 440.0 37.83 MB

CareKit is an open source software framework for creating apps that help people better understand and manage their health.

Home Page: https://www.researchandcare.org

License: Other

Swift 100.00%
carekit swift5 combine uiframework health swift-package-manager core-data darkmode-ios13

carekit's Introduction

CareKit

CareKit

License Swift Versions OS's Xcode 14.0+ SPM

CareKit™ is an open source software framework for creating apps that help people better understand and manage their health. The framework provides modules that you can use out of the box, or extended and customized for more targeted use cases. It's composed of three SPM packages which can each be imported separately.

  • CareKit: This is the best place to start building your app. CareKit provides view controllers that tie CareKitUI and CareKitStore together. The view controllers leverage Combine to provide synchronization between the store and the views.

  • CareKitUI: Provides the views used across the framework. The views are open and extensible subclasses of UIView. Properties within the views are public, allowing for full control over the content.

  • CareKitStore: Provides a Core Data solution for storing patient data. It also provides the ability to use a custom store, such as a third party database or API.

Table of Contents

Requirements

The primary CareKit framework codebase supports iOS and requires Xcode 12.0 or newer. The CareKit framework has a Base SDK version of 13.0.

Getting Started

Option One: Install using Swift Package Manager

You can install CareKit using Swift Package Manager. Create a new Xcode project and navigate to File > Swift Packages > Add Package Dependency. Enter the URL https://github.com/carekit-apple/CareKit and tap Next. Choose the main branch, and on the next screen, check off the packages as needed.

To add localized strings to your project, add the strings file to your project: English Strings

Option Two: Install as an embedded framework

Download the project source code and drag in CareKit.xcodeproj, CareKitUI.xcodeproj, and CareKitStore.xcodeproj as needed. Then, embed each framework in your app by adding them to the "Embedded Binaries" section for your target as shown in the figure below.

embedded-framework

OCKCatalog App

The included catalog app demonstrates the different modules that are available in CareKit: OCKCatalog

ockcatalog

OCKSampleApp

The included sample app demonstrates a fully constructed CareKit app: OCKSample

ocksample

CareKit

CareKit is the overarching package that provides view controllers to tie CareKitUI and CareKitStore together. When importing CareKit, CareKitUI and CareKitStore are imported under the hood.

List view controllers

CareKit offers full screen view controllers for convenience. The view controllers query for and display data from a store, and stay synchronized with the data.

  • OCKDailyTasksPageViewController: Displays tasks for each day with a calendar to page through dates.

  • OCKContactsListViewController: Displays a list of contacts in the store.

Synchronized View Controllers

For each card in CareKitUI, there's a corresponding view controller in CareKit. The view controllers are self contained modules that you can place anywhere by using standard view controller containment. The view controller for each card provides synchronization between the view and the store. The following code creates a synchronized view controller.

// Create a store to hold your data.
let store = OCKStore(named: "my-store", type: .onDisk)

// Create a view controller that queries for and displays data. The view will update automatically whenever the data in the store changes.
let viewController = OCKSimpleTaskViewController(taskID: "doxylamine", eventQuery: OCKEventQuery(for: Date()), store: store)

All synchronized view controllers have a view synchronizer. The view synchronizer defines how to instantiate the view to display, and how to update the view when the data in the store changes. You can customize view synchronizers and inject them into a view controller to perform custom behavior.

// Define a custom view synchronizer.
class CustomSimpleTaskViewSynchronizer: OCKSimpleTaskViewSynchronizer {

    override func makeView() -> OCKSimpleTaskView {
        let view = super.makeView()
        // Customize the view when it's instantiated here.
        return view
    }

    override func updateView(_ view: OCKSimpleTaskView, context: OCKSynchronizationContext<OCKTaskEvents>) {
        super.updateView(view, context: context)
        // Update the view when the data changes in the store here.
    }
}

// Instantiate the view controller with the custom classes, then fetch and observe data in the store.
var query = OCKEventQuery(for: Date())
query.taskIDs = ["Doxylamine"]

let viewController = OCKSimpleTaskViewController(query: query, store: store, viewSynchronizer: CustomSimpleTaskViewSynchronizer())

Custom Synchronized View Controllers

CareKit supports creating a custom view that can pair with a synchronized view controller. This allows synchronization between the custom view and the data in the store.

// Define a view synchronizer for the custom view.
class TaskButtonViewSynchronizer: ViewSynchronizing {

    // Instantiate the custom view.
    func makeView() -> UIButton {
        return UIButton(frame: CGRect(x: 0, y: 0, width: 200, height: 60))
    }

    // Update the custom view when the data in the store changes.
    func updateView(
        _ view: UIButton,
        context: OCKSynchronizationContext<OCKAnyEvent?>
    ) {
        let event = context.viewModel
        view.titleLabel?.text = event?.task.title
        view.isSelected = event?.outcome != nil
    }
}

var query = OCKEventQuery(for: Date())
query.taskIDs = ["Doxylamine"]

let events = store
    .anyEvents(matching: query)
    .map { $0.first }

let viewController = SynchronizedViewController(
    initialViewModel: nil,
    viewModels: events,
    viewSynchronizer: TaskButtonViewSynchronizer()
)

CareKitUI

CareKitUI provides cards to represent tasks, charts, and contacts. There are multiple provided styles for each category of card.

You build all cards in a similar pattern. This makes it easy to recognize and customize the properties of each card. Cards contain a headerView at the top that displays labels and icons. The contents of the card are inside a vertical contentStackView. This allows for easy placement of custom views into a card without breaking existing constraints.

For creating a card from scratch, see the OCKCardable protocol. Conforming to this protocol makes it possible for a custom card to match the styling used across the framework.

Tasks

Here are the available task card styles:

Task

This example instantiates and customizes the instructions task card:

let taskView = OCKInstructionsTaskView()

taskView.headerView.titleLabel.text = "Doxylamine"
taskView.headerView.detailLabel.text = "7:30 AM to 8:30 AM"

taskView.instructionsLabel.text = "Take the tablet with a full glass of water."

taskView.completionButton.isSelected = false
taskView.completionButton.label.text = "Mark as Completed"

Charts

Here are the available chart card styles:

Chart

This example instantiates and customizes the bar chart:

let chartView = OCKCartesianChartView(type: .bar)

chartView.headerView.titleLabel.text = "Doxylamine"

chartView.graphView.dataSeries = [
    OCKDataSeries(values: [0, 1, 1, 2, 3, 3, 2], title: "Doxylamine")
]

Contacts

Here are the available contact card styles:

Contact

This example instantiates and customizes the simple contact card:

let contactView = OCKSimpleContactView()

contactView.headerView.titleLabel.text = "Lexi Torres"
contactView.headerView.detailLabel.text = "Family Practice"

Styling

To provide custom styling or branding across the framework, see the OCKStylable protocol. All stylable views derive their appearance from a list of injected constants. You can customize this list of constants for quick and easy styling.

Here's an example that customizes the separator color in a view, and all of it's descendents:

// Define your custom separator color.
struct CustomColors: OCKColorStyler {
    var separator: UIColor { .black }
}

// Define a custom struct to hold your custom color.
struct CustomStyle: OCKStyler {
    var color: OCKColorStyler { CustomColors() }
}

// Apply the custom style to your view.
let view = OCKSimpleTaskView()
view.customStyle = CustomStyle()

Note that each view in CareKitUI is styled with OCKStyle by default. Setting a custom style on a view propagates the custom style down to any subviews that don't already have a custom style set. You can visualize the style propagation rules in this diagram demonstrating three separate view hierarchies:

Styling

For information on styling SwiftUI views with OCKStylable, see SwiftUI in CareKitUI.

CareKitStore

The CareKitStore package defines the OCKStoreProtocol that CareKit uses to communicate to data stores, and a concrete implementation that leverages CoreData, called OCKStore. It also contains definitions of most of the core structures and data types that CareKit relies on, such as OCKAnyTask, OCKTaskQuery, and OCKSchedule.

Store

The OCKStore class is an append-only, versioned store packaged with CareKit. It's implemented on top of CoreData and provides fast, secure, on-device storage. OCKStore is designed to integrate with CareKit's synchronized view controllers, but is usable in isolation as well.

import CareKitStore

let store = OCKStore(named: "my-store", type: .onDisk)
let breakfastSchedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: Date(), end: nil, text: "Breakfast")
let task = OCKTask(id: "doxylamine", title: "Doxylamine", carePlanID: nil, schedule: breakfastSchedule)

let storedTask = try await store.addTask(task)

The most important feature of OCKStore is that it's a versioned store with a notion of time. When querying the store using a date range, the result returned is for the state of the store during the interval specified. If no date interval is provided, the query returns all versions of the entity.

// On January 1st
let task = OCKTask(id: "doxylamine", title: "Take 1 tablet of Doxylamine", carePlanID: nil, schedule: breakfastSchedule)
let addedTask = try await store.addTask(task)

// On January 10th
let task = OCKTask(id: "doxylamine", title: "Take 2 tablets of Doxylamine", carePlanID: nil, schedule: breakfastSchedule)
let updatedTask = try await store.updateTask(task)

// On some future date.
let earlyQuery = OCKTaskQuery(dateInterval: /* Jan 1st - 5th */)
let earlyTasks = try await store.fetchTasks(query: earlyQuery)

let laterQuery = OCKTaskQuery(dateInterval: /* Jan 12th - 17th */)
let laterTasks = try await store.fetchTasks(query: laterQuery)

// Queries return the newest version of the task during the query interval.
let midQuery = OCKTaskQuery(dateInterval: /* Jan 5th - 15th */)
let midTasks = try await store.fetchTasks(query: laterQuery)

// Queries with no date interval return all versions of the task.
let allQuery = OCKTaskQuery()
let allTasks = try await store.fetchTasks(query: allQuery)

This graphic visualizes how to retrieve results when querying versioned objects in CareKit. Note how a query over a date range returns the version of the object that's valid in that date range.
3d608700-5193-11ea-8ec0-452688468c72

Schema

CareKitStore defines six high level entities in this diagram:

Schema

  • Patient: A patient represents the user of the app.

  • Care Plan: A patient has zero or more care plans. A care plan organizes the contacts and tasks associated with a specific treatment. For example, a patient may have one care plan for heart disease and a second for obesity.

  • Contact: A care plan has zero or more associated contacts. Contacts might include doctors, nurses, insurance providers, or family.

  • Task: A care plan has zero or more tasks. A task represents some activity that the patient performs. Examples include taking a medication, exercising, journaling, or checking in with their doctor.

  • Schedule: Each task must have a schedule. The schedule defines occurrences of a task, and may optionally specify target or goal values, such as how much of a medication to take.

  • Outcome: Each occurrence of a task may have an associated outcome. The absence of an outcome indicates no progress was made on that occurrence of the task.

  • Outcome Value: Each outcome has zero or more values associated with it. A value might represent how much medication was taken, or a plurality of outcome values could represent the answers to a survey.

It's important to note that tasks, contacts, and care plans can exist without a parent entity. Many CareKit apps target well defined use cases, and it can often be expedient to simply create tasks and contacts without defining a patient or care plan.

Scheduling

The scheduling tools provided in CareKit allow very precise and customizable scheduling of tasks. You create an instance of OCKSchedule by composing one or more OCKScheduleElements. Each element defines a single repeating interval.

Static convenience methods exist to help with common use cases.

let breakfastSchedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: Date(), end: nil, text: "Breakfast")
let everySaturdayAtNoon = OCKSchedule.weeklyAtTime(weekday: 7, hours: 12, minutes: 0, start: Date(), end: nil)

You can create highly precise, complicated schedules by combining schedule elements or other schedules.

// Combine elements to create a complex schedule.
let elementA = OCKScheduleElement(start: today, end: nextWeek, interval: DateComponents(hour: 36))
let elementB = OCKScheduleElement(start: lastWeek, end: nil, interval: DateComponents(day: 2))
let complexSchedule = OCKSchedule(composing: [elementA, elementB])

// Combine two schedules into a composed schedule.
let dailySchedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: tomorrow, end: nextYear, text: nil)
let crazySchedule = OCKSchedule(composing: [dailySchedule, complexSchedule])

Schedules have a number of other useful properties that you can set, including target values, durations, and textual descriptions.

let element = OCKScheduleElement(
    start: today,  // The date and time this schedule begins.
    end: nextYear, // The date and time this schedule ends.
    interval: DateComponents(day: 3), // Occurs every 3 days.
    text: "Before bed", // Show "Before bed" instead of clock time.
    targetValues: [OCKOutcomeValue(10, units: "mL")], // Specifies what counts as "complete".
    duration: Duration = .hours(2) // The window of time to complete the task.
)
  • text: By default, CareKit view controllers prompt users to perform tasks using clock time, such as "8:00PM". If you provide a text property, then CarKit uses the text to prompt the user instead, such as "Before bed" in the code above.

  • duration: If you provide a duration, CareKit prompts the user to perform the scheduled task within a window, such as "8:00 - 10:00 PM". You can also set the duration to .allDay if you don't wish to specify any time in particular.

  • targetValues: CareKit uses target values to determine if a user completed a specific task. See OCKAdherenceAggregator for more information.

Custom Stores and Types

The OCKStore class that CareKit provides is a fast, secure, on-device store that serves most use cases. It may not fully meet the needs of all developers, so CareKit also allows you to write your own store. For example, you could write a wrapper around a web server, or even a simple JSON file. You can use any class that conforms to the OCKStoreProtocol in place of the default store.

Writing a CareKit store adapter requires defining the entities that live in your store, and implementing asynchronous Create, Read, Update, and Delete methods for each. Stores are free to define their own types, as long as those types conform to a certain protocol. For example, if you're writing a store that can hold tasks, you might do it like this.

import CareKitStore

struct MyTask: OCKAnyTask & Equatable & Identifiable {

    // MARK: OCKAnyTask
    let id: String
    let title: String
    let schedule: String
    /* ... */

    // MARK: Custom Properties
    let difficulty: DifficultyRating
    /* ... */
}

struct MyTaskQuery: OCKAnyTaskQuery {

    // MARK: OCKAnyTaskQuery
    let ids: [String]
    let carePlanIDs: [String]
    /* ... */

    // MARK: Custom Properties
    let difficult: DifficultyRating?
}

class MyStore: OCKStoreProtocol {

    typealias Task = MyTask
    typealias TaskQuery = MyTaskQuery
    /* ... */

    // MARK: Task CRUD Methods
    func fetchTasks(query: TaskQuery, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<[Task]>) { /* ... */ }
    func addTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) { /* ... */ }
    func updateTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) { /* ... */ }
    func deleteTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) { /* ... */ }

    /* ... */
}

Using the four basic CRUD methods you supply, CareKit is able to use protocol extensions to imbue your store with extra functionality. For example, a store that implements the four CRUD methods for tasks automatically receives the following methods.

func fetchTask(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<Task>)
func addTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure<Task>?)
func updateTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure<Task>?)
func deleteTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure<Task>?)

The provided methods employ naive implementations. You're free to provide your own implementations that leverage the capabilities of your underlying data store to achieve greater performance or efficiency.

If you're considering implementing your own store, read over the protocol notes and documentation carefully.

Getting Help

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

License

This project is made available under the terms of a BSD license. See the LICENSE file.

carekit's People

Contributors

akshay-yadav-apple avatar apbendi avatar auibrian avatar brynbodayle avatar cbaker6 avatar cyhsutw avatar erik-apple avatar gavirawson-apple avatar jrames avatar jwstaiert avatar kelseydedoshka-apple avatar lguba avatar macroyau avatar matteocrippa avatar mirlhaq avatar moppymopperson avatar ninoguba avatar nizar avatar npsantini avatar pariecemckinney-apple avatar programmarchy avatar rajitss avatar srinathtm-apple avatar stevemoser avatar tktsubota avatar uberjason avatar umerkhan-apple avatar vtourraine avatar weijentu avatar yuanzhu-apple avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

carekit's Issues

Crush in OCKCareCardWeekView

Values array provided for setValues with items count more than 7 will crush app by accessing index out of bounds of _heartButtons. See here

[OCKCareCard] Add a delegate method to request custom behavior for certain cells

Prior to 1.0.2 this class was public, which was useful when I wanted to present a custom view controller via the delegate methods only part of the time (based on some condition), and display the default detail view controller the rest of the time--I could still manually instantiate OCKCareCardDetailViewController. Assuming this was intentionally made private, is there an alternative for manually accessing it?

Ignoring event's cache when using simulator

I noticed if you create an OCKCarePlanActivity object and run your app one time , some of the event's data is getting cached and next time that you change that object you're not gonna see the changes.

Rendering OCKInsightsChartTableViewCell causes lags

Hi. Rendering a table view cell of the OCKInsightsChartTableViewCell class takes too much time. I can clearly see lags when I'm scrolling the table view with the cells of that class.
I have some time measures:

OCKTest[362:69627] Cell for row for class OCKInsightsMessageTableViewCell with time: 0.008754
OCKTest[362:69627] Cell for row for class OCKInsightsChartTableViewCell with time: 0.108796
OCKTest[362:69627] Cell for row for class OCKInsightsMessageTableViewCell with time: 0.003148
OCKTest[362:69627] Cell for row for class OCKInsightsChartTableViewCell with time: 0.080318
OCKTest[362:69627] Cell for row for class OCKInsightsMessageTableViewCell with time: 0.001522
OCKTest[362:69627] Cell for row for class OCKInsightsChartTableViewCell with time: 0.124296
OCKTest[362:69627] Cell for row for class OCKInsightsChartTableViewCell with time: 0.129740
OCKTest[362:69627] Cell for row for class OCKInsightsMessageTableViewCell with time: 0.000314
OCKTest[362:69627] Cell for row for class OCKInsightsMessageTableViewCell with time: 0.000287

The same we can see at Time Profiler tool (screenshot below).

screen shot 2016-05-05 at 1 59 58 am

Local Notification Reminder for Activity

Hi @umerkhan-apple,

First of all thanks a lot for such a wonderful presentation on WWDC - Getting Started with CareKit #237.
At the event you showed Pt Pal app developed extending CareKit.

It would be wonderful if the activity in CarePlan Store itself had the such field for different time in a day, and not only option to give number of times a day.

vlcsnap-2016-06-18-21h57m37s308

Q1. Is there work going on Care Kit to support such feature to allow exact time for event during a day ? If not would you suggest to send pull request extending current framework to store time of the day.

Q2. If Yes on Q1; is Care Kit about to support Local notification support in future, for the use case like in Pt Pal app ? Again would you sending pull request for this case adding helper for Local Notification for activity ?

OCKCareSchedule cannot be subclassed in swift

OCKCareSchedule.init() is marked as NS_UNAVAILABLE and the initialiser initWithStartDate(...) is set as private. The documented comments advise to inherit from OCKCareSChedule and call initWithStartDate. In this Swift this is not possible. (Not sure but it may not be possible in Objective C too)

Sample doesn't exclude data from backup

According to the guidelines for CareKit and ResearchKit based apps data should not be stored in iCloud. Thus the data file(s) created in sample app for CareKit should be excluded from backup by using the NSURLIsExcludedFromBackupKey key but are not currently. Also is there a way to exclude files from being backed up to iCloud and unencrypted iTunes backups but not encrypted iTunes backups like Health.app does?

ORKCarePlanStore.setEndDate doesn't take effect on the activity's schedule

I added an activity to the store without an endDate set initially.

I use the setEndDate function of the CarePlanStore to set it to today and it returned successful.

BUT the activity's endDate remained nil.

Documentation below says what I'm doing is suppose to work:

Once an activity has been added to a store, only the endDate can be changed by using the setEndDate:forActivity:completion: method.

Bug?

Group items in CareCard and SymptomTracker Views

It would be great if the activities that appear in both the Care Card and Symptom Tracker views can be grouped based on the CarePlan Activity's group identifier.

And to go further, it would be ideal if the order of these groups and items can be programmatically controlled.

createPDFDataWithCompletion

Receiving an EXC_BAD_ACCESS self.webview error in OCKHTMLPDFWriter.m when trying to create an OCKDocument from a OCKBarChart. The error occurs when I attempt to access the document data using 'document.createPDFDataWithCompletion' which was defined in Apple's Documentation.

Crash on the care card

When tapping an intervention row on the Care Card with the accessibility inspector enabled, a exception is thrown:

2016-07-07 12:53:21.934 OCKSample[31203:5647838] -[UITableViewCellAccessibilityElement interventionEvents]: unrecognized selector sent to instance 0x7f9471c731e0
2016-07-07 12:53:21.936 OCKSample[31203:5647838] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCellAccessibilityElement interventionEvents]: unrecognized selector sent to instance 0x7f9471c731e0'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000102cc0d85 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x0000000104b92deb objc_exception_throw + 48
    2   CoreFoundation                      0x0000000102cc9d3d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x0000000102c0fcfa ___forwarding___ + 970
    4   CoreFoundation                      0x0000000102c0f8a8 _CF_forwarding_prep_0 + 120
    5   CareKit                             0x00000001029a9a72 -[CareCardAccessibilityElement accessibilityValue] + 130
    6   UIAccessibility                     0x00000001162d0894 -[NSObject(AXPrivCategory) accessibilityAttributeValue:] + 1449
    7   UIAccessibility                     0x00000001162bc449 _copyMultipleAttributeValuesCallback + 381
    8   AXRuntime                           0x0000000116350dea _AXXMIGCopyMultipleAttributeValues + 215
    9   AXRuntime                           0x000000011634bc98 _XCopyMultipleAttributeValues + 467
    10  AXRuntime                           0x0000000116358e8f mshMIGPerform + 235
    11  CoreFoundation                      0x0000000102be6579 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    12  CoreFoundation                      0x0000000102be64e9 __CFRunLoopDoSource1 + 473
    13  CoreFoundation                      0x0000000102bdbc60 __CFRunLoopRun + 2272
    14  CoreFoundation                      0x0000000102bdb0f8 CFRunLoopRunSpecific + 488
    15  GraphicsServices                    0x00000001070ecad2 GSEventRunModal + 161
    16  UIKit                               0x0000000103616f09 UIApplicationMain + 171
    17  OCKSample                           0x0000000102501be2 main + 114
    18  libdyld.dylib                       0x0000000107c7292d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Implicitly, it also affects any UITests that involve the OCKCareCardViewController

CocoaPod ignores project umbrella header, header visibility.

The current podspec causes CocoaPods to rewrite the umbrella header for the framework that it creates so that it is out of sync with the actual umbrella header CareKit.h. Various headers are included in the umbrella that probably shouldn't be, and are listed in the CareKit target as 'public' when they should be 'project'.

Heart View Appears to Lag When Moving To/From 0% or 100%

When toggling an event complete or not complete the animation of the OCKHeartView appears to be delayed when moving to or from 0% or 100%.

The problem is that the frame of the OCKHeartView is larger than the heart image itself, so there is some hidden animation occurring which gives the appearance of lag.

This is most noticeable in the OCKSample app since it has 4 events on the Care Card.

Symptom Tracker does not display multiple circles if an activity has multiple events

The doc on Symptom Tracker states:

Assessment activities also require valid schedule, title, and text parameters. The schedule sets the number of circles to be filled on each day.

However, in actuality, OCKSymptomTrackerViewController displays a new row for every assessment activity. If one has multiple events, it simply appears on more than one row.

Not sure if the doc is wrong or if the code is wrong, but to me, what is documented is the more appropriate behavior.

Adding activity with identical identifier results in odd callback parameters

The documentation states that it is not possible to add an activity with an identical identifier to one already stored (https://github.com/carekit-apple/CareKit/blob/master/CareKit/CarePlan/OCKCarePlanStore.h#L108).

So far, in a number of tests, it seems to me that adding an activity with an existing identifier results in a callback with YES for the success parameter and with an error populated stating an activity with the identifier already exists. No activity is actually added. This seems counter intuitive, but it's not clear to me what the expected behavior should be.

Note that any app that attempts to add an activity after the first start of the app will encounter this behavior. The sample app also depends on it. (https://github.com/carekit-apple/CareKit/blob/master/Sample/OCKSample/SampleData.swift#L94)

Diving into the implementation, unless I'm totally missing something (always possible!), the behavior does not seem to be intended. For one, the app nil checks the "inout" error parameter that was passed into the method two times, when it seems the intention was to nil check the local errorOut.

Additionally, even if the first check was corrected, I'm not sure I understand it's purpose. It seems to me you'd want to return the subsequent error if an item were found, or return the value of the errorOut variable if something else went wrong.

I'm happy to take a stab at solving this, but want to clear up what the actual intended behavior is. Should the store return an error anytime an activity with the same identifier is added? (As far as I can tell, this would mean apps would have to take care to only add activities at first start, or when first added. This may in fact be reasonable, but I wanted to confirm given the behavior of the sample app).

[Request] iPad Support

Right now the sample app - OCKSample is iPhone only application. Which can be change to support iPad as well. App looks okay and runs fine, but crashes on "Connect" screen when we try to share via "Send Report"
carekit share send report
It give following error -

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController (<_UIAlertControllerActionSheetRegularPresentationController:>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'

General Question extending OCKCarePlanStore Model

I'd like to extend the OCKCarePlanStore to add additional data to activities. The problem is the OCKCarePlanStore model has no property to store additional kind of data. As I haven't seen any recommendation in the documentation to do so, I think this should be a part of the documentation or at least for a blog entry.

For example, I'd like to create an activity that contains a property videos containing plain links to some video stream. where should I start?

Thank you!

Assigning 0 contacts to connect view controller forces its view to load

Another nitpick: Assinging a zero-length array to the contacts view controller's contacts property calls the prepareHeaderView method, which will call [self.view addSubview:], forcing the view to load. An isViewLoaded call would be great.

let controller = OCKConnectViewController(coder: ...)
...
controller.contacts = []    // <--

Changes in care plan

The documentation for CareKit seems to indicate that if one wants to change what is a Careplan, the old care plan has to be deleted and a new one instantiated. If that is the case, Carekit would be impractical as in real life care plan changes occur all the time (say take this medication A 2 times a day to take a different medication B 5 times a day). See statement "As you iteratively develop and test your app, you often need to change the design of your treatment plan. This usually means removing the old activities before you can add new ones." http://carekit.org/docs/docs/AccessingCarePlanData/AccessingCarePlanData.html

Optional intervention activity

Often a certain medication should be taken only when some conditions are met. For example, if when in pain, take x number of pill of y type, an deduct it from the daily dosage. The optional intervention activities could also be other things and not only medication, but it would be available when the given conditions are met.

Example
The patient suddenly experiences pain, and reports the symptom. Since the pain is moderate, the intervention activity then suggests using medication X. If the pain was more severe, the suggestion then would be medication Y. After 30 minutes, a notification reminds the patient to report the pain again, if the value is lower, then everything is OK. If the pain value rises, of course within the parameters set by the care giver/doctor, a new intervention activity is suggested.

Regarding reporting, the optional medication should not count against the care completion percentage, because when it did, patients would be encouraged to take medication just so the heart fills up.

CareCard / SymptomTracker - Allow Customization

I noticed that some CareCard and SymptomTracker classes are not open to customization.
For instance:

If one wants to change the TableHeader of the CareCard, currently that's not possible.
If one wants to draw different Table Cells for the CareCard, this is also not possible.
Some customizations like that are blocked by the way the classes are designed.
Is this an expected behavior? Or you guys are open to changes on that?

Optional Symptoms that do not contribute to the percent complete?

I need to implement a symptom tracker that has 4 required symptoms that must be tracked over a 7 days (that is straight forward). I also need to have another 20 symptoms that may occur and I dont want the user to have to fill these in. I think its easier that if the user doesn't select it then you assume that they haven't had that symptom. Instead of going through and having to interact with 20 symptoms that you dont have.

The 4 important symptoms have to show as completed and the rest shouldn't interfere with the days completion percentage.

  1. How is it possible to work with a list view or other selection processes when you present the view to input the level of your symptom that you can use in Research Kit? I cannot see how you can have say multiple choice questions?
    Sorry I am using swift and cant change the Obj C code to suite.

Adding an activity to the store returns success even if there is an existing activity with same identifier

Add an activity with the same identifier as an existing activity in the store returns true in the success of the completion event, however there is an error.

if success means the method completed ok, then the sample app should be changed to look at the error field, not just the success field.

if success means the activity was added ok, then its returning the wrong value. it should be false.

BP Display

Hi,

Is there a way of displaying blood pressure results, in the same way that there is in HealthKit? Can't see anything in the charting functions to do this.

Is there a simple solution to this without having to write a custom function?

Automatically record an intervention activity

In the WWDC session video it was mentioned that an intervention activity could be automatically checked off with data from HealthKit. How would I start implementing something like this? Create an observer for the HealthKit store? Could something like this be added to the sample app?

Care card sub-labels, optional reps, rich descriptions

First, noob alert. I only started programming after I discovered CareKit. Sorry if I'm missing something super obvious -- if there are, I would appreciate your kind explanations 👍

I have a few suggestions for the Care Card, if this is an appropriate place to discuss it.

  1. Sub-labels / differentiation of occurrences. For example, if a pill is to be taken three times daily, there would be 3 occurrences under the said pill in the Care Card. However, the left, middle and the right circles are counted the same: if they were to be labeled morning, afternoon and evening, and the middle one is left unchecked (signifying the afternoon dose was skipped), this might potentially be an interesting piece of information to the physician.
  2. Optional/flexible number of occurrences. For example, a post-surgery recovery protocol requires the patient to walk down the hall x number of times every day (say, at least three times). I guess this could be asked in the Symptom Tracker, but it's a to-do item for the patient and I believe it belongs in the Care Card.
  3. Rich descriptions. I guess I wanted to put something like a ResearchKit Active Task in the description for, as an example, an exercise. At the very least I want to put some pictures or movie clips to demonstrate how one could perform the said exercise. To me the OCKSample program doesn't seem to suggest that I could do this, but it'd be pretty useful if I could.

That's it for now -- thanks for reading.

Why the software history was not kept?

Hi there,

I'm a researcher studying software evolution. As part of my current research, I'm studying the implications of open-sourcing a proprietary software, for instance, if the project succeed in attracting newcomers. CareKit was in my list. However, I observed that the software history of when the software was developed as a proprietary software was not kept after the transition to Github.

Knowing that software history is indispensable for developers (e.g., developers need to refer to history several times a day), I would like to ask CareKit developers the following four brief questions:

  1. Why did you decide to not keep the software history?
  2. Do the core developers faced any kind of problems, when trying to refer to the old history? If so, how did they solve these problems?
  3. Do the newcomers faced any kind of problems, when trying to refer to the old history? If so, how did they solve these problems?
  4. How does the lack of history impacted on software evolution? Does it placed any burden in understanding and evolving the software?

Thanks in advance for your collaboration,

Gustavo Pinto, PhD
http://www.gustavopinto.org

Can you initialize OCKCareCardViewController using StoryBoard?

Let's say I'm using the StoryBoard to design my app with multiple tabs in a TabViewController and one of these tabs is the OCKCareCardViewController. So far from the documentation and sample app, this can only be instantiated and added to the TabViewController programmatically.

Is it possible to have your own symptoms input?

I want to use the care kit system but within my own UI. Is there a way to save the symptom scores without the care kit UI? I want to keep the activity completion part of the System Tracker page.

Request for Tutorial

Hope this finds all of you well! My team and I are complete amateurs to programming, app development, GitHub, you name it. But we are really excited about the prospects of CareKit. Despite our fumbling around on various walk-throughs and online resources, we have been unsuccessful in building an app leveraging CareKit's framework. In short: we don't know what we are doing and want to ask you for some guidance.

We are wondering if anyone can point us to some helpful resources that we have so far been unable to find. Ideally, we are hoping to find someone interested in giving us a tutorial on CareKit and navigating Xcode generally. We would pay you for your time, and we don't expect this to be too time-intensive (just a few hours of your time). Would anyone be interested in scheduling a tutorial for $100/hour? Feel free to e-mail me at [email protected] if you are interested.

We are at a point where we have hit a wall and need some tactical questions answered. Please let me know if there is a better forum for me to direct this request. I apologize if this request is inappropriate for this venue.

Thanks in advance and have a great weekend!

-Joe

Contact "monogram" described as optional but nonoptional in initializer

Sorry to be nitpicking, this is a minor point. The description of monogram for an OCKContact says:

If a monogram is not provided, the image will be used for the contact

I think the opposite is happening: if there is no image, the monogram will be used. Hence it always has to be provided as a fallback.

allow activities to be discontinued

If an app allows the user to add OCKCarePlanActivity, it would be useful to allow the user to discontinue them. The Card View could allow a swipe-left gesture on an activity to allow the user to discontinue the activity immediately, or "tomorrow".

Some thoughts on implementing this:

  • we would likely not want activities obtained from an EHR to be deferred by the user. OCKCarePlanActivity could have a canBeDeferred flag, which would default to false.
  • the OCKCareCardViewControllerDelegate could be expanded to include a careCardViewController:canDeferInterventionActivity: operation which would allow developers to specify whether or not an activity can be deferred, and could be called as OCKCareCardTableViewCells are being created in OCKCareCareViewController's tableView:cellForRowAtIndexPath.

@umerkhan-apple: We discussed leveraging careCardViewController:willDisplayEvents..., but I don't see how that would be used after looking at the code. I believe we were thinking that the developer would specify which events would be deferrable here.

OCKCarePlanEvents would need similar functionality to allow them be discontinued as well.

Ability to control display order in CareCard/SymptomTracker

It would be nice if there were a straightforward way to control display order in OCKSymptomTrackerViewController/OCKSymptomTrackerViewController.

The :willDisplayEvents:dateComponents: delegate methods allow changes to the events themselves associated with the OCKCarePlanStore used in initialization. The displayed data is ultimately populated using that store with [_tableView reloadData]. The display order is determined by the order in which the activities were added to the OCKCarePlanStore.

Is OCKCarePlanStore intended to be the persistent single source of truth for CareKit apps?

Ways around this include creating a parallel database that serves as the authoritative data source, and creating and populating new OCKCarePlanStores from that for the view controllers. This works but creates a lot of parallel work and may impact performance. One could also (this is a terrible idea) fetch the activities and their associated events, remove and re-add the activities in the desired order, and reconstruct the events for each activity using OCKCarePlanStore API methods.

Straightforward solutions may include adding a displayOrder field to the CoreData model (seems polluting to the model). Alternatively, the OCKCarePlanStore could expose its NSManagedObjectContext, allowing the creation of a CoreData hierarchy as described here. This way, a 'parent' store would control the persistence/writes and be the source of truth, and 'child' OCKCarePlanStores could be created and populated for the view controllers on-demand, populated with the subsets of relevant data in whatever order. Event changes in the child contexts would be passed to the 'parent' for persistence to disk. Does this seem reasonable?

Any suggestions are appreciated.

OCKCarePlanStore should also have functions to get events of activities with a certain group identifier and enumerate them

Similar to the following:

http://carekit.org/docs/Classes/OCKCarePlanStore.html#//api/name/eventsForActivity:date:completion:
http://carekit.org/docs/Classes/OCKCarePlanStore.html#//api/name/enumerateEventsOfActivity:startDate:endDate:handler:completion:

There should also be the following counterpart functions for activities with a specified group identifier.

  • eventsForActivitiesWithGroupIdentifier
  • enumerateEventsOfActivitiesWithGroupIdentifier

[CareCard] Date appears wrong for certain time zones.

The date on the CareCard is constructed by converting an NSDate in the local time zone -> NSDateComponents in UTC with no sense of the time of day -> NSDate with time 00:00:00 -> NSString formatted in the local time zone.

In PST, date should be Wed, May 11, 2016 but is rendered as Wed, May 10, 2016

screen shot 2016-05-11 at 11 10 52 am

Move codebase to Swift

Hey guys,

I would love to help migrating the codebase to Swift. Is there an interest in this? It would probably be done in a fork or - even better - in an own branch to ensure that master still can be synced. Thanks guys!

Hans

No such module ResearchKit

When I try to build the sample app, I get the error "no such module ResearchKit" in the HealthSampleBuilder.swift source file.

[Request] CareKit CocoaPod

Adding CocoaPods as a method for installing the framework would enable seamless version management of the framework in projects already utilizing CocoaPods for dependency management. It also lets a developer import the framework even faster, and better matches the existing ResearchKit project installation options.

ResearchKit can be a dependency, allowing a developer to import both ResearchKit and CareKit pods into his or her project with a single declaration of CareKit in the pod file.

How to get the last selected intervention event?

With SymptomTrackerViewController, it provides the lastSelectedAssessmentEvent method to get access to the last assessment event.

I need the same for CareCardViewController but unfortunately it's not provided.

What I'm doing is present a custom TaskViewController on the didSelectRowWithInterventionActivity and didSelectButtonWithInterventionEvent delegates of the CareCardViewController but once the TaskViewController finishes with .Completed reason, I need to do something and I need to know the exact InterventionEvent that initiated it. Would be great if the CareCardViewController can also provide the last selected Intervention Event.

Any suggestions how to do this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.