Skip to content

YapDatabaseCloudKit with Swift value types #291

@heiberg

Description

@heiberg

TLDR: Best strategy when you can't use KVO and stateful/mutable model objects?

(I'd tag this as a question, because I'm really just seeking advice here.)

Current setup: I have an app, written in Swift, which uses YapDatabase. My models are plain structs. The objects going in and out of the database are NSCoding compliant helper classes, which are created on-demand when reading and writing. These helpers are short lived and not passed around the app.

(In case it's relevant, the application in question is using @danthorpe 's delightful YapDatabaseExtensions to accomplish this.)

Now I am trying to add CloudKit sync to this app, learning as I go from the CloudKitTodo example.

The approach taken in CloudKitTodo with a smart superclass (MyDatabaseObject) won't work in this environment, so I'm trying to come up with a good alternative to MyDatabaseObject.

This is where I'm feeling a bit stuck, as I'm still pretty new to both YapDatabase and CloudKit.

In order to implement the record handler and merge blocks I need to answer questions about what changed in the object.

By using Swift structs I've opted out of KVO and type introspection. This is obviously a trade-off and I'm perfectly happy to diff two instances myself, field by field.

I think my question is:

What would be an elegant way to get access to both the original and modified value in the record handler block?

I believe the recordHandler is invoked too late for me to read the original from the database?

I could use my NSCoding helper to add a shadow copy to my struct. This would carry over unchanged when creating new, modified values and be available when saving. Conceptually something like this (ignore that recursive value types are illegal):

struct Person {
    let name: String
    let syncInfo: Person? // Not persisted. Only read when saving.
}

Or perhaps I could duplicate the data in the database. Either in a parallel collection or in the metadata. This would double my local storage cost, but my data is so small that it would be acceptable.

Maybe I could somehow compare against fields in the CKRecord? If no CKRecord is found it's a newly inserted object and all fields must be updated.

I apologize if this comes of as a bit rambling. I feel like I just barely know enough to phrase the question.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions