GithubHelp home page GithubHelp logo

Comments (9)

sjrmanning avatar sjrmanning commented on June 11, 2024 1

No problem, thanks for reaching out and I'm glad we were able to determine the issue! If you ever want to test with a fresh state, deleting and re-installing the app should clear that isZoneCreated flag from UserDefaults.

from sample-cloudkit-privatedb-sync.

sjrmanning avatar sjrmanning commented on June 11, 2024

Hi @ghecho — can you see records being created in CloudKit Console? Note that you may have to use the "Act as iCloud Account" feature that shows up in the bottom left menu when inspecting your CloudKit Database to inspect data for the same account your devices are logged into. Also does the same issue occur on your iOS device?

from sample-cloudkit-privatedb-sync.

ghecho avatar ghecho commented on June 11, 2024

Hi @sjrmanning .

I just logged-in to the CloudKit console and then I signed in via "Act as iCloud Account" with the account that's used on the devices and tried to see the records on the private database but no, I don't see any records in the CloudKit Console. I expected to see the record type of Contacts but I only see the default Users type:

Screenshot 2023-07-17 at 15 45 36

from sample-cloudkit-privatedb-sync.

sjrmanning avatar sjrmanning commented on June 11, 2024

Do you see any logs from CloudKit in the console? It seems like the save operation is failing, but there could be a few reasons why. In Xcode, under your target (e.g. "PrivateSync") in "Signing & Capabilities" do you see your container listed with a checkmark against it under the iCloud section?

It might be useful to add some logging to the database.save operation in ViewModel.swift's addContact function, something like this:

func addContact(name: String) async throws {
    let newRecordID = CKRecord.ID(zoneID: zone.zoneID)
    let newRecord = CKRecord(recordType: "Contact", recordID: newRecordID)
    newRecord["name"] = name

    do {
        let savedRecord = try await database.save(newRecord)
        let savedRecordName = savedRecord.recordID.recordName

        await MainActor.run {
            contacts[savedRecordName] = name
        }
        await saveLocalCache()
    } catch {
        debugPrint("Error saving contact: \(error)")
        throw error
    }
}

This will print out the error coming back from that database.save operation if it fails.

from sample-cloudkit-privatedb-sync.

ghecho avatar ghecho commented on June 11, 2024

Yes, the container was checked and NOT in red, it was black.

I added the logging and indeed the save operation was failing with this error:

"Error saving contact: <CKError 0x282dc4a50: \"Permission Failure\" (10/2007); server message = \"Invalid bundle ID for container\"; op = D75D9DD7D04D9C5A; uuid = 91BE5144-9469-4805-A71A-033AEB0AF32B; container ID = \"iCloud.my.org.bundle.here.PrivateSync\">"

Which seemed wierd. I re-checked that the App bundle ID was correct and that the iCloud Container id was the same but with the iCloud prefix and that it was the same in the Config.swift but I couldn't find any error.

I decided to create a new App ID my.org.bundle.here.privatesync1 with the corresponding container ID iCloud.my.org.bundle.here.privatesync1. I waited for Xcode to register the new ID and then clicked refresh on the iCloud container so it changed from red to black and then I ran the app, but now there's another error when trying to save:

Error saving contact: <CKError 0x281fa2e80: \"Bad Container\" (5/1014); \"Couldn\'t get container configuration from the server for container \"iCloud.my.org.bundle.here.privatesync1\"\">

I waited a few minutes without changing any code and then I ran the app again and now the error is:

Error saving contact: <CKError 0x28105df80: \"Zone Not Found\" (26/2036); server message = \"Zone does not exist\"; op = 42C3E47BEE3BDBB2; uuid = 06211F3E-A5D0-4E1B-A5CC-2351989466AB; container ID = \"iCloud.my.org.bundle.here.privatesync1\">

from sample-cloudkit-privatedb-sync.

ghecho avatar ghecho commented on June 11, 2024

So, I left more time pass in case there was something pending to propagate internally on CloudKit but no, same error Zone Not Found. I checked the code and I see that this should not happen since I'm seeing that there's a createZoneIfNeeded() function that should create the zone. Still, I was not seeing the zone Contacts on the CloudKit dashboard, so I manually created it on the private database.

I waited a couple minutes but I'm still seeing the same error.

from sample-cloudkit-privatedb-sync.

ghecho avatar ghecho commented on June 11, 2024

Ok, here's an update. I think I solved it.

  1. I deleted the app from one device and I told it also to delete the associated data.
  2. I rebuilt the app and put a breakpoint here:
Screenshot 2023-07-18 at 12 03 45

But it kept skipping the guard statement, I was super confused and not sure if the user defaults key was persisted even if the app was deleted.

  1. I commented that guard clause and re-run the app
  2. The app started working
  3. I uncommented the guard clause to revert to the original code
  4. The app now works as expected.

So here's my theory. I think that the guard clause has a bug in it. I think it should not be negated, right? From a quick look into the code, it's the same issue for the subscriptions.

I created a PR for this. Could you take a look in case I'm missing something in the PR?

Also, I'm still not sure why it didn't work when I manually created the zone on the private DB on the dashboard. Maybe the Zones are inside the user's private DB and independent of each others? Maybe I should've created using the "Act as iCloud Account" using the same account as the one on the devices?

from sample-cloudkit-privatedb-sync.

sjrmanning avatar sjrmanning commented on June 11, 2024

So it sounds like the original issue was that the bundle ID you used wasn't associated with the container you were using (Invalid bundle ID for container).

The guard clause is actually correct; another way to read it is isZoneCreated must be false, otherwise return (don't re-create zone). What likely happened is at some point you ran this on a device (maybe with another container, or bundle ID), the UserDefaults was false, so it tried to create a zone, and it succeeded and set that bool isZoneCreated to true, so on subsequent runs (with another container/bundle ID), it didn't even try to create a zone when it in fact needed to.

Regarding the zone creation on the dashboard, that's probably right — zones in the private database are still per-user, so unless your developer account and the iCloud account you're testing with are the same, you would need to use "Act as iCloud Account" to create the zone.

from sample-cloudkit-privatedb-sync.

ghecho avatar ghecho commented on June 11, 2024

It's weird, I double checked that it was not in red and that the part after iCloud matched the App Bundle ID 🤷🏻‍♂️. I have no idea what happened. I'm just glad that it's working now.

Ohh, I see my mistake with isZoneCreated . Yes, it's correct here on the repo. Sorry about that. I'll close my PR 😅.

BTW It now works perfectly and pretty much instantaneously. Thanks for the help.

from sample-cloudkit-privatedb-sync.

Related Issues (6)

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.