Repository navigation
Replies: 1 comment 1 reply
|
Hey @W1W1-M, thanks for bringing this up. I have actually attempted this tool in the past but got mired in some details. We definitely should try it again. A few questions:
This is the first I've heard of needing to prime shares in CloudKit. What does this accomplish?
This is also the first time I've heard of this tool. Do you have any example of what the output looks like? |
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Hello,
Before promoting the CloudKit schema from Development to Production, it's hard to be sure every column has a field. Core Data offers
NSPersistentCloudKitContainer.initializeCloudKitSchema(options:)for this; SwiftData apps can use it through a temporary Core Data container. SQLiteData has nothing equivalent yet. In smaller apps this is generally not a problem because everything can be easily/quickly tested and then gets synced without too much worry. As apps become bigger and more complexe there is more risk of a field not being synced a least once before dev schema is promoted to production.Why testing one record per table isn't enough
CloudKit Development only creates a field when a record is saved with a non-nil value for it. When a column is nil,
CKRecord.removeValue(forKey:at:)(CloudKit+StructuredQueries.swift) writes only thesqlitedata_icloud_userModificationTime_<column>companion. It never writes the value field, or<column>_hashfor BLOB columns. So a record type can exist in Development while some optional columns have no field. After deploying, the first save in Production that sets one of those columns fails. Uploading a blank record per table wouldn't help, because a blank record leaves every optional column nil.In my app,
estimatedValueCurrencyCode,latitude/longitude, and a couple of optionalBLOBs were never set during testing. I only noticed because I went looking.Why the library is the right place for this
The placeholder values have to produce the same CloudKit field types that real saves produce. For example, a
Datestored as TEXT becomes a timestamp field, andUUID,BoolandBLOBcolumns each have their own encoding. App code can only get this right by inserting real rows through the models. I do that today with a DEBUG helper that inserts one fully populated row per table, sends, then deletes. It has to be updated by hand whenever a column is added. SQLiteData already knows each table'swritableColumnsand their bindings, so it could do this generically.Possible shape
try await syncEngine.initializeCloudKitSchema(), DEBUG / Development only. For each synced table it would upload a record with every field set (assets included), then delete it. Optionally it would also create and delete a share, socloudkit.shareexists for apps that use sharing.Thanks for any feedback and also considering this!
PS : written by me with the help of Claude
All reactions