As mentioned these activities are hard coded. Even if I change the data, the app is not updated unless I delete and reinstall. How would one go about changing or adding activities dynamically?
Beyond that, the object is immutable. It makes some sense. If you were to create an activity, and the user completes several associated events, you wouldnât want to change the activity. For instance, they might have jogged 1 mile every day for a week - and then you change the activity to indicate 2 miles. Theyâve suddenly got invalid data from past events.
The correct way to do this is to create a totally new event. You can check if it already exists by looking for itâs UUID, and if it doesnât, you create it. If for some reason you really need to replace it, you can delete the activity (which removes its associated events) and replace it with a similar one that has your tweaks.
Note the CarePlanStore has a removeActivity:completion: for this purpose.
Thank you jeffry, yes. Removing and adding the activity makes sense, and Iâve done that. Except the existing controller still wonât update with the new activity from the store.
let carePlanManager = CarePlanStoreManager()
carePlanManager.store.remove(breastActivity, completion: {success , error in
print ("Trying to remove: error: ", error)
print ("Trying to remove: success: ", error)
})
carePlanManager.store.add(breastActivity,completion:
{success , error in
print("Adding: Error: ", error)
print("Adding: Success: ", success)
})
let viewController = OCKCareCardViewController(carePlanStore: carePlanManager.store)
self.navigationController?.pushViewController(viewController, animated: true)
The new viewController shows the new activity corrrectly. Is there something I should do so the the existing tab bar view controller fetches the new activities in the store manager?
I just did a test where I added and removed an activity as you described, and my Care Card did update.
Took another look at your question and I see the issue, if this sample code is pulled from your actual implementation. Here youâve started by creating a new CarePlanStoreManager, from which you remove and then add the activity.
If you are leveraging the CarePlanStoreManager from ZombieKit, you should change your code to reference CarePlanStoreManager.sharedCarePlanStoreManager. This is a singleton that you can use to maintain a reference to the single OCKCarePlanStore used by the project.
Calling CarePlanStoreManager() directly as you did will basically create a new store over the old one. And since your OCKCareCardViewController is hooked up to the old one (which you passed it when you initialized the controller), it doesnât see the updates you made.
And thanks (very much) for the tutorials. It may be a little late, but could you comment on the design decisions in CareKit? For example, it seems odd that so many closures would require both a âsuccessâ parameter and an âerrorâ parameter. Also, it seems strange that the call to the CarePlanStore would pass the retrieved object into a completion closure rather than to the code that is making the call. (The âaddâ function shows instances of both approaches).
According to the documentation on Github all calls to the CarePlanStore (other than the call to create the store) are run asynchronously. You have to provide a closure just to get the data back to your app.
So sorry for the delay. I had your original note in my inbox, and things got busy to the point where it dropped off the inbox and my radar.
You are absolutely right about the reason behind the CarePlanStore activity(forIdentifier:completion:) returning the activity in a closure. This way, you can provide code you want to run using the retrieved activity once it comes back.
As for many closures returning both a success and error parameter - this is a fairly common practice in many APIs. While itâs true you could check the error and consider a nil to be success - thatâs not a great practice. For instance, a nil return could mean there was a problem processing the return message, and youâd get the opposite result than what was intended.
In the add example, I have a guard up top to confirm the return was successful using success. But as you noticed, I didnât do anything with the error. In practice, youâd want to throw something inside the else of the guard that does something with the error response. For example, you might pop up an alert telling the user what went wrong. In the case of the tutorial, I was trying to simplify where I could, and so generic error handling didnât make the cut.
I hope that helps, and thanks for reading the tutorial! If you have other questions, I promise to get back to you in less than a month :]
Hello Jeff
Great tutorial!!
I was wondering how would I write assessment for the timed walk test which is part of the active task assessments research kit? This is what I have so far,
public var timedWalk: ORKOrderedTask {
return ORKOrderedTask.timedWalk(withIdentifier: âTimed Walkâ, intendedUseDescription: âAssessment measures balanceâ, distanceInMeters: 3, timeLimit: 13, includeAssistiveDeviceForm: true, options: .excludeConclusion) }
This was written in assessment factory file. How would I write this code so I can implement this into carekit?
thanks
So I was able to get the timed walking test to display on on symptomViewcontroller.
static func timedWalkAssessment() â ORKTask {
return ORKOrderedTask.shortWalk(withIdentifier: âShort Walk Assessmentâ, intendedUseDescription: âEstimate your fall Riskâ, numberOfStepsPerLeg: 20, restDuration: 60, options: .excludeHeartRate)
}
}
Hope this helps
This tutorial is more than six months old so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]