{"id":13828896,"url":"https://github.com/Sorix/CloudCore","last_synced_at":"2025-07-09T06:33:27.011Z","repository":{"id":70366748,"uuid":"80771430","full_name":"Sorix/CloudCore","owner":"Sorix","description":"Framework that enables syncing between iCloud (CloudKit) and Core Data","archived":true,"fork":false,"pushed_at":"2022-06-01T19:58:17.000Z","size":331,"stargazers_count":153,"open_issues_count":17,"forks_count":40,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-08-05T09:18:32.434Z","etag":null,"topics":["cloudkit","cocoapods","core-data","coredata","swift","swift-package-manager","sync","synchronization"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sorix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-02-02T21:41:24.000Z","updated_at":"2024-07-10T00:50:49.000Z","dependencies_parsed_at":"2023-02-26T12:31:29.522Z","dependency_job_id":null,"html_url":"https://github.com/Sorix/CloudCore","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sorix%2FCloudCore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sorix%2FCloudCore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sorix%2FCloudCore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sorix%2FCloudCore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sorix","download_url":"https://codeload.github.com/Sorix/CloudCore/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225492420,"owners_count":17482869,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudkit","cocoapods","core-data","coredata","swift","swift-package-manager","sync","synchronization"],"created_at":"2024-08-04T09:03:18.321Z","updated_at":"2024-11-20T08:31:18.790Z","avatar_url":"https://github.com/Sorix.png","language":"Swift","readme":"# Archived\n\nNowdays repository is not actively maintained, so I put that repo in an archived state because I can't provide high-quality support and actual updates for that project. Maybe a little later I could take control of that and push a new version of CloudCore.\n\nI recommend looking at [Deeje's pull request](https://github.com/Sorix/CloudCore/pull/51), he has implemented a lot of fixes and new features, but it's not my code so I couldn't guarantee anything.\n\n# CloudCore\n\n[![Documentation](https://sorix.github.io/CloudCore/badge.svg)](https://sorix.github.io/CloudCore/)\n[![Version](https://img.shields.io/cocoapods/v/CloudCore.svg?style=flat)](https://cocoapods.org/pods/CloudCore)\n![Platform](https://img.shields.io/cocoapods/p/CloudCore.svg?style=flat)\n![Status](https://img.shields.io/badge/status-beta-orange.svg)\n![Swift](https://img.shields.io/badge/swift-4-orange.svg)\n\n**CloudCore** is a framework that manages syncing between iCloud (CloudKit) and Core Data written on native Swift. It maybe used are CloudKit caching.\n\n#### Features\n* Sync manually or on **push notifications**.\n* **Differential sync**, only changed object and values are uploaded and downloaded. CloudCore even differs changed and not changed values inside objects.\n* Respects of Core Data options (cascade deletions, external storage).\n* Knows and manages with CloudKit errors like `userDeletedZone`, `zoneNotFound`, `changeTokenExpired`, `isMore`.\n* Covered with Unit and CloudKit online **tests**.\n* All public methods are **[100% documented](https://sorix.github.io/CloudCore/)**.\n* Currently only **private database** is supported.\n\n## How it works?\nCloudCore is built using \"black box\" architecture, so it works invisibly for your application, you just need to add several lines to `AppDelegate` to enable it. Synchronization and error resolving is managed automatically.\n\n1. CloudCore stores *change tokens* from CloudKit, so only changed data is downloaded.\n2. When CloudCore is enabled (`CloudCore.enable`) it fetches changed data from CloudKit and subscribes to CloudKit push notifications about new changes.\n3. When `CloudCore.fetchAndSave` is called manually or by push notification, CloudCore fetches and saves changed data to Core Data.\n4. When data is written to persistent container (parent context is saved) CloudCore founds locally changed data and uploads it to CloudKit.\n\n## Installation\n\n### CocoaPods\n**CloudCore** is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'CloudCore', '~\u003e 2.0'\n```\n\n## How to help?\nCurrent version of framework hasn't been deeply tested and may contain errors. If you can test framework, I will be very glad. If you found an error, please post [an issue](https://github.com/Sorix/CloudCore/issues).\n\n## Documentation\nAll public methods are documented using [XCode Markup](https://developer.apple.com/library/content/documentation/Xcode/Reference/xcode_markup_formatting_ref/) and available inside XCode.\nHTML-generated version of that documentation is [**available here**](https://sorix.github.io/CloudCore/).\n\n## Quick start\n1. Enable CloudKit capability for you application:\n![CloudKit capability](https://cloud.githubusercontent.com/assets/5610904/25092841/28305bc0-2398-11e7-9fbf-f94c619c264f.png)\n\n2. Add 2 service attributes to each entity in CoreData model you want to sync:\n  * `recordData` attribute with `Binary` type\n  * `recordID` attribute with `String` type\n\n3. Make changes in your **AppDelegate.swift** file:\n\n```swift\nfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -\u003e Bool {\n  // Register for push notifications about changes\n  application.registerForRemoteNotifications()\n\n  // Enable CloudCore syncing\n  CloudCore.enable(persistentContainer: persistentContainer)\n\n  return true\n}\n\n// Notification from CloudKit about changes in remote database\nfunc application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -\u003e Void) {\n  // Check if it CloudKit's and CloudCore notification\n  if CloudCore.isCloudCoreNotification(withUserInfo: userInfo) {\n    // Fetch changed data from iCloud\n    CloudCore.fetchAndSave(using: userInfo, to: persistentContainer, error: nil, completion: { (fetchResult) in\n      completionHandler(fetchResult.uiBackgroundFetchResult)\n    })\n  }\n}\n\nfunc applicationWillTerminate(_ application: UIApplication) {\n\t// Save tokens on exit used to differential sync\n\tCloudCore.tokens.saveToUserDefaults()\n}\n```\n\n4. Make first run of your application in a development environment, fill an example data in Core Data and wait until sync completes. CloudCore create needed CloudKit schemes automatically.\n\n## Service attributes\nCloudCore stores service CloudKit information in managed objects, you need to add that attributes to your Core Data model. If required attributes are not found in entity that entity won't be synced.\n\nRequired attributes for each synced entity:\n1. *Record Data* attribute with `Binary` type\n2. *Record ID* attribute with `String` type\n\nYou may specify attributes' names in 2 ways (you may combine that ways in different entities).\n\n### User Info\nFirst off CloudCore try to search attributes by looking up User Info at your model, you may specify User Info key `CloudCoreType` for attribute to mark one as service one. Values are:\n* *Record Data* value is `recordData`.\n* *Record ID* value is `recordID`.\n\n![Model editor User Info](https://cloud.githubusercontent.com/assets/5610904/24004400/52e0ff94-0a77-11e7-9dd9-e1e24a86add5.png)\n\n### Default names\nThe most simple way is to name attributes with default names because you don't need to specify any User Info.\n\n### 💡 Tips\n* You can name attribute as you want, value of User Info is not changed (you can create attribute `myid` with User Info: `CloudCoreType: recordID`)\n* I recommend to mark *Record ID* attribute as `Indexed`, that can speed up updates in big databases.\n* *Record Data* attribute is used to store archived version of `CKRecord` with system fields only (like timestamps, tokens), so don't worry about size, no real data will be stored here.\n\n## Example application\nYou can find example application at [Example](/Example/) directory.\n\n**How to run it:**\n1. Set Bundle Identifier.\n2. Check that embedded binaries has a correct path (you can remove and add again CloudCore.framework).\n3. If you're using simulator, login at iCloud on it.\n\n**How to use it:**\n* **+** button adds new object to local storage (that will be automatically synced to Cloud)\n* **refresh** button calls `fetchAndSave` to fetch data from Cloud. That is useful button for simulators because Simulator unable to receive push notifications\n* Use [CloudKit dashboard](https://icloud.developer.apple.com/dashboard/) to make changes and see it at application, and make change in application and see ones in dashboard. Don't forget to refresh dashboard's page because it doesn't update data on-the-fly.\n\n## Tests\nCloudKit objects can't be mocked up, that's why I create 2 different types of tests:\n\n* `Tests/Unit` here I placed tests that can be performed without CloudKit connection. That tests are executed when you submit a Pull Request.\n* `Tests/CloudKit` here located \"manual\" tests, they are most important tests that can be run only in configured environment because they work with CloudKit and your Apple ID.\n\n  Nothing will be wrong with your account, tests use only private `CKDatabase` for application.\n\n  **Please run these tests before opening pull requests.**\n To run them you need to:\n  1. Change `TestableApp` bundle id.\n  2. Run in simulator or real device `TestableApp` target.\n  3. Configure iCloud on that device: Settings.app → iCloud → Login.\n  4. Run `CloudKitTests`, they are attached to `TestableApp`, so CloudKit connection will work.\n\n## Roadmap\n\n- [x] Move from alpha to beta status.\n- [ ] Add `CloudCore.disable` method\n- [ ] Add methods to clear local cache and remote database\n- [ ] Add error resolving for `limitExceeded` error (split saves by relationships).\n\n## Author\n\nOpen for hire / relocation.\nVasily Ulianov, [va...@me.com](http://www.google.com/recaptcha/mailhide/d?k=01eFEpy-HM-qd0Vf6QGABTjw==\u0026c=JrKKY2bjm0Bp58w7zTvPiQ==)\n","funding_links":[],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSorix%2FCloudCore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSorix%2FCloudCore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSorix%2FCloudCore/lists"}