Open shirblc opened 2 years ago
(e.g., do I have to create a custom store in order to create a custom type?)
Yep! The OCKStore
only knows how to store the OCK<Entity>
types. Once you start adding new properties, you'll have to write store methods that will store/fetch those new properties. Once you write a few of the custom methods, some others will be synthesized automatically for you (IE fetchEvent(...)
if you conform your task to OCKAnyVersionableTask
).
If you have just a few new properties that you don't need to query against, there is a lightweight alternative you can consider. Each entity has a userInfo
dictionary where you can put those properties to be later retrieved.
var task = OCKTask(...)
task.userInfo["priority"] = "1"
store.addTask(task)
I see, thank you very much for the full explanation!
In that case, wouldn't it be clearer not to have the default OCKStore
conforming to the Any<Entity>
protocols? Or at least make sure that the error and/or documentation indicate that it's required? (Or is it stated somewhere and I missed it?)
Also, is there any documentation on how to create/handle custom stores (other than this bit from the README)? Since there are different store protocols, does that mean I can recreate just the parts I need to customise, or do I have to recreate the entire store? Do I need to set up the whole CoreData stack, too, or it it enough to define the relevant classes?
Thank you again!
In that case, wouldn't it be clearer not to have the default OCKStore conforming to the Any
protocols?
Conforming to the type-erased entity protocols allows developers to use any type of store across CareKit. While it does provides flexibility, the downside is that you lose type safety. See this method below as an example of a seam where type safety is lost:
We can try and explore some ways to bring type safety back while maintaining the flexibility of using any store. There have been some recent changes to Swift that will be very helpful.
Also, is there any documentation on how to create/handle custom stores
We unfortunately do not have a good example, but feel free to post questions here and I can help you out along the way. If you're interested, you can document the process and modify the Readme!
does that mean I can recreate just the parts I need to customise
Great question, it depends. If you're calling CRUD methods on your store, you can absolutely split it up into parts. But if you're using the CareKit view controllers, they require the full fledged OCKAnyStoreProtocol
. We're working on modifying what the view controller needs so that you don't need to implement the full store protocol.
That makes sense. But since the methods don't work, shouldn't there be a warning (at least; it might make more sense to make it a fatal error), to let people know that a custom OCKAnyStore
is required? (Although, as you've said, with Swift 5.6 we might not even need it.)
Thank you! I will definitely document the entire thing so that it's easier for anyone else interested in this. Is there any other written documentation I can add to, other than the README and carekit-apple.github.io? Or a way to add to the latter? Would love to write an in-depth guide on how to use it, but it might be too long for the README...
I'm using a couple of CareKit's view controllers, so as per your comment, I've started building an entire store. I think most of the methods are pretty straightforward, since they seem to be based around regular Core Data objects, but I'm not sure how to handle events and adherence. I thought an event would have its own model, but it doesn't seem to, so how/where are events stored? I know the OCKAnyStore
protocol only requires read methods, but since I'm not sure how they're stored, I'm not sure how to read them either. And also, I assumed the CareKitStore handles the logic of creating events and updating them with outcomes once those are available, but if I'm creating my own store, do I need to do that myself, or is that handled by CareKit's extensions, like the one mentioned in the AnyStore section of the README?
As far as the Core Data store handling goes, I'm guessing I'll need to create the model for any object that I change, right? So how much of the original Core Data functionality do I need to rebuild for these Any objects? I saw CareKit's models are defined in CareKitStore/CoreData, and the code is generated manually and is based on OCKCDVersionedObject (which is a subclass of OCKCDObject), so do I need to rebuild all that functionality as well?
Thank you again for all the help and the detailed answers!
I've only just noticed the OCKAnyVersionableTask
protocol (while setting up my Core Data stack). Is that how CareKit handles events? (Xcode still insists I'm missing required methods for Events in my custom OCKAnyStore, which makes me think I'm missing something. Probably something in how it's all connected and stored in Core Data, which I'm still not sure about.)
But since the methods don't work, shouldn't there be a warning (at least; it might make more sense to make it a fatal error)
We pass back an error to the caller, I would definitely recommend checking that whenever adding tasks to the store. There are a few issues that could pop up.
Is there any other written documentation I can add to
The Readme is the best spot!
how much of the original Core Data functionality do I need to rebuild for these Any objects
The answer there sort of depends on what your custom models look like. What model requirements have led you to create custom models?
I've only just noticed the OCKAnyVersionableTask protocol
Yep. If you'd like your task to be versioned, you can conform your task to that protocol. As an added benefit, you'll get the fetchEvent
methods synthesized for you for free.
Hi!
Thank you so much for all the work you do on CareKit and ResearchKit.
I have a question about the Any types (OCKAnyPatient etc). I've been trying to add my own custom type of patient to the store, but I keep getting this error:
CareKitStore.OCKStoreError.addFailed(reason: "Failed to add patients. Not all patients were of the correct type: OCKPatient")
.I've done some digging and it looks like my app fails here. The debugger shows that:
Which I'm guessing means that instead of using the associated Patient type defined in the
OCKReadablePatientStore
, it uses the default OCKStore Patient type. I couldn't find where it's set, but it looks like the OCKStore accepted types definition, hence my guess.The same thing also happens when I try to add a custom plan. I haven't tried the other types, but I doubt it'll go any differently.
Is that supposed to be happening? Am I missing a step in adding a custom type? (e.g., do I have to create a custom store in order to create a custom type?) I've made sure my patient type conforms to
OCKAnyPatient
and I'm using thestore.addAnyPatients
method, which according to the docs seems like it should be enough, but it's entirely possible I missed something.Thank you!