iCloud Synchronization doesn’t work

I’m trying to sync data from the AppData on one device to another device with the same iCloud. It uploads the data to the CloudKit but it doesn’t write the data it fetches from the cloud into the AppData storage. It should store a timestamp, a few integers, and two lists of integers. The lists are both optional and store numbers. They can have 0 up to 50 numbers in them.

This is the part where it should fetch the records and store them in the AppData

        let container = CKContainer(identifier: "iCloud.com.calchunt")
        let privateDatabase = container.privateCloudDatabase
        
        let dispatchGroup = DispatchGroup()
        var errors: [Error] = []
        
        // Leere Liste zum Speichern neuer Spielsitzungen aus der Cloud
        var newGameSessions: [AppModule.GameSession] = []
        
        for gameSession in gameSessions {
            let recordIDString = gameSession.id.uuidString // UUID zu String umwandeln
            let recordID = CKRecord.ID(recordName: recordIDString)
            
            dispatchGroup.enter()
            privateDatabase.fetch(withRecordID: recordID) { (existingRecord, error) in
                defer { dispatchGroup.leave() }
                if let error = error {
                    // Fehler beim Abrufen des Records
                    print("Fehler beim Abrufen des Records aus CloudKit: \(error.localizedDescription)")
                    errors.append(error)
                } else if let existingRecord = existingRecord {
                    // Record existiert in der Cloud
                    print("Record mit ID \(existingRecord.recordID.recordName) existiert in CloudKit")
                    // Überprüfen, ob der Record bereits im AppModule vorhanden ist
                    if let _ = gameSessions.firstIndex(where: { $0.id == gameSession.id }) {
                        // Record existiert bereits im AppModule, überspringe das Speichern
                        print("Record mit ID \(existingRecord.recordID.recordName) existiert bereits im AppModule, überspringe das Speichern")
                    } else {
                        // Record existiert nicht im AppModule, füge ihn zur Liste der neuen Spielsitzungen hinzu
                        let newGameSession = AppModule.GameSession(
                            id: gameSession.id,
                            losungszahl: gameSession.losungszahl,
                            elapsedTime: gameSession.elapsedTime,
                            currentDate: gameSession.currentDate,
                            skipped: gameSession.skipped,
                            skipped2: gameSession.skipped2,
                            level: gameSession.level
                        )
                        newGameSessions.append(newGameSession)
                        print("Record mit ID \(existingRecord.recordID.recordName) wird zum AppModule hinzugefügt")
                    }
                } else {
                    // Record existiert nicht in der Cloud
                    print("Record mit ID \(recordID.recordName) existiert nicht in CloudKit")
                }
            }
        }
        
        dispatchGroup.notify(queue: .main) {
            if !errors.isEmpty {
                for error in errors {
                    print("Fehler beim Abrufen der Daten aus CloudKit: \(error.localizedDescription)")
                }
            } else {
                // Füge neue Spielsitzungen zum AppModule hinzu
                gameSessions.append(contentsOf: newGameSessions)
                // Speichere die aktualisierten Daten im AppStorage
                do {
                    let encoder = JSONEncoder()
                    let gameSessionsData = try encoder.encode(gameSessions)
                    GameSessions = gameSessionsData
                    print("Daten erfolgreich aus CloudKit geladen und im AppStorage gespeichert")
                } catch {
                    print("Fehler beim Codieren und Speichern der Daten im AppStorage: \(error.localizedDescription)")
                }
            }
        }
    }

I think you can start with checking if privateDatabase.fetch(withRecordID: recordID returns data. If it does, you can focus on debugging why the data isn't persisted; otherwise, check if the record ID is right, or if the fetch returns any error. In either case, you narrow down the scope quite a bit.

Worth mentioning, your code puts the fetch in a for loop, which does one fetch for each gameSession, and uses DispatchGroup to serialize the fetches. Is there any special reason that you need to do so? If not, that can be replaced by you gathering the record IDs first and using records(for:desiredKeys:) to fetch the records all at once.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

iCloud Synchronization doesn’t work
 
 
Q