Fabien
Fabien

Reputation: 1

How to synchronize Core Data with Ensembles Framework?

I would like to use Ensembles Framework to synch my core data with Swift.

Ensembles Framework

But I have some difficulties..

I try to do it like that: (Similar way to the example on github) I use a button to launch the tasks:

class ReglagesVC: UIViewController,UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate,CDEPersistentStoreEnsembleDelegate {

 @IBAction func IcloudSynch(_ sender: UIButton) {

        CDESetCurrentLoggingLevel(CDELoggingLevel.verbose.rawValue)

        // Setup Core Data Stack
        self.setupCoreData()       

        // Setup Ensemble
        let modelURL = Bundle.main.url(forResource: "Mes_Vide_os", withExtension: "momd")
        cloudFileSystem = CDEICloudFileSystem(ubiquityContainerIdentifier: nil)
        ensemble = CDEPersistentStoreEnsemble(ensembleIdentifier: "Mes_Vide_os", persistentStore: storeURL, managedObjectModelURL: modelURL!, cloudFileSystem: cloudFileSystem)
        ensemble.delegate = self

        // Listen for local saves, and trigger merges
        NotificationCenter.default.addObserver(self, selector:#selector(localSaveOccurred(_:)), name:NSNotification.Name.CDEMonitoredManagedObjectContextDidSave, object:nil)
        NotificationCenter.default.addObserver(self, selector:#selector(cloudDataDidDownload(_:)), name:NSNotification.Name.CDEICloudFileSystemDidDownloadFiles, object:nil)

        // Sync
        self.sync(nil)  
    }


    //ENSEMBLES

    // MARK: Notification Handlers

    func localSaveOccurred(_ notif: Notification) {
        self.sync(nil)
    }

    func cloudDataDidDownload(_ notif: Notification) {
        self.sync(nil)
    }

    let appDelegate = UIApplication.shared.delegate as! AppDelegate



    var storeDirectoryURL: URL {
        return try! FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    }

    var storeURL: URL {
        return self.storeDirectoryURL.appendingPathComponent("store.sqlite")
    }
    var managedObjectContext : NSManagedObjectContext!
    func setupCoreData() {
        let modelURL = Bundle.main.url(forResource: "Mes_Vide_os", withExtension: "momd")//"momd"
        let model = NSManagedObjectModel(contentsOf: modelURL!)

        try! FileManager.default.createDirectory(at: self.storeDirectoryURL, withIntermediateDirectories: true, attributes: nil)

        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model!)
        let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
        try! coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: self.storeURL, options: options)

        managedObjectContext = appDelegate.persistentContainer.viewContext
        managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    }


    // MARK: Ensembles

    var cloudFileSystem: CDECloudFileSystem!
    var ensemble: CDEPersistentStoreEnsemble!

    func sync(_ completion: (() -> Void)?) {
        //let viewController = self.window?.rootViewController as! ReglagesVC
        //self.activityIndicator?.startAnimating()

        if !ensemble.isLeeched {
            ensemble.leechPersistentStore {
                error in
                print("LEECH FINI___________________________")
                completion?()
            }
        }
        else {
            ensemble.merge {
                error in
                print("MERGE FINI___________________________")
                completion?()
            }
        }
    }

    func persistentStoreEnsemble(_ ensemble: CDEPersistentStoreEnsemble, didSaveMergeChangesWith notification: Notification) {

        managedObjectContext.performAndWait {
            self.managedObjectContext.mergeChanges(fromContextDidSave: notification)
        }
    }

    func persistentStoreEnsemble(_ ensemble: CDEPersistentStoreEnsemble!, globalIdentifiersForManagedObjects objects: [Any]!) -> [Any]! {
        let Films = objects as! [BaseFilms]
        print("films map")
        return Films.map { $0.id }
    }

}

And when I login my cloudkit dashboard I see that a container with has been created but there isn't any recors in the datas folder.

And nothing is synchonised between my devices.

Can you tell me where I am wrong??

Thank you.

Upvotes: 0

Views: 452

Answers (2)

Fabien
Fabien

Reputation: 1

To solve my issues:

  1. Put the code in the correct place (in the AppDelegate).

  2. Install the latest update of Ensembles (1.7.1 instead of 1.7).

And that's all! Thank you Drew.

Just one thing still strange: When I add an object in one device it is synchronised on the other but when I delete an object it's not deleted on the other device and created again on the first device.

Upvotes: 0

Drew McCormack
Drew McCormack

Reputation: 3592

By putting the setup code in an action, my guess is you are creating a new Ensemble (and Core Data stack) every time you press the button. You should setup the stack and ensemble once, perhaps on launch in viewDidLoad, and keep it in a property.

Note that the first time you call sync, it will "leech". This involves importing your local data, but it does not upload anything. The second time you call sync, it will download data from the cloud and upload. So you need to call sync twice — with the same ensemble object — before you will see any data in the CloudKit web interface.

Note also that you can only see data in CloudKit from the logged in user. So you still won't see anything unless you login there with the account you are testing with.

Upvotes: 0

Related Questions