IceCream helps you sync Realm Database with CloudKit.

“It works like magic!”

Features

  • Realm Database

    • Off-line First
    • Thread Safety
    • Reactive Programming
  • Apple CloudKit

    • Automatical Authentication
    • Silent Push
  • Reachability(Support Long-lived Operation)

  • Error Handling

  • Sync Automatically

  • Manually Synchronization is also supported

  • User Account Status Check

  • Complete Documentation

Prerequisite

  1. Be sure to have enrolled in Apple Developer Program

  2. Turn on your iCloud in Capabilities and choose CloudKit

  3. Turn on Background Modes and check Background fetch and Remote notification

Usage

Basics

  1. Prepare your Realm Object
class Dog: Object {
    @objc dynamic var id = NSUUID().uuidString
    @objc dynamic var name = ""
    @objc dynamic var age = 0
    @objc dynamic var isDeleted = false

    override class func primaryKey() -> String? {
        return "id"
    }
}Copy the code
  1. Make your Realm Object conform to CKRecordConvertible and CKRecordRecoverable
extension Dog: CKRecordConvertible {
    /// recordName : this is the unique identifier for the record, used to locate records on the database. We can create our own ID or leave it to CloudKit to generate a random UUID.
    /// For more: https://medium.com/@guilhermerambo/synchronizing-data-with-cloudkit-94c6246a3fda
    var recordID: CKRecordID {
        return CKRecordID(recordName: id, zoneID: Constants.customZoneID)
    }
    
    var record: CKRecord {
        // Simultaneously init CKRecord with zoneID and recordID, thanks to this guy: https://stackoverflow.com/questions/45429133/how-to-initialize-ckrecord-with-both-zoneid-and-recordid
        let r = CKRecord(recordType: Dog.recordType, recordID: recordID)
        r[.id] = id as CKRecordValue
        r[.age] = age as CKRecordValue
        r[.name] = name as CKRecordValue
        r[.isDeleted] = isDeleted as CKRecordValue
        return r
    }
    
    static var customZoneID: CKRecordZoneID {
        return CKRecordZoneID(zoneName: "DogsZone", ownerName: CKCurrentUserDefaultName)
    }

    static var recordType: String {
        return "Dog"
    }
}

extension Dog: CKRecordRecoverable {
    static func objectFrom(record: CKRecord) -> Object? {
        guard let id = record[.id] as? String,
            let age = record[.age] as? Int,
            let name = record[.name] as? String,
            let isDeleted = record[.isDeleted] as? Bool
            else { return nil }
        
        let dog = Dog()
        dog.id = id
        dog.age = age
        dog.name = name
        
        return dog
    }
}Copy the code
  1. Start the Engine!
var syncEngine: SyncEngine<Dog>?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    ...
    syncEngine = SyncEngine<Dog>()
    application.registerForRemoteNotifications()
    ...
}Copy the code

That’s all you need to do! Everytime you write to Realm, the SyncEngine will get notified and handle sync stuffs!

For more details, clone the project to see the source code.

About Object Deletions

Yep, we highly recommend you use Soft Deletions. That’s why we add a isDeleted property to CKRecordConvertible protocol.

When you want to delete a object, you just need to set its isDeleted property to true. And the rest of things are already taken care of.

You also don’t need to worry about the clean-up things. It has also been considered.

Example project is provided to see the detailed usage.

Requirements

  • IOS 10.0 +
  • Swift 4
  • Realm Swift ~ > 3.0

Debug Suggestions

It’s true that debugging CloudKit is hard and tedious. But I have some tips for you guys when facing puzzles.

Warning: If you’re going to launch your app onto App Store, don’t forget to deploy your environment settings to production. You can do it easily in the CloudKit Dashboard. Write & Read permissions are also need to be considered.

One More Tip

How to debug CloudKit in production mode? See this post.

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Installation

IceCream is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'IceCream'Copy the code

To-Do List

  • CKReference & Realm’s LinkingObjects
  • CloudKit Shared Database
  • Supports Other platforms, like macOS, tvOS and watchOS

Make it better

  1. Fork this project
  2. Do your changes
  3. Feel free to submit a pull request

Live Demo

A Lightweight task management app is using IceCream. You can download it and try it on your app muiltiple devices to see this magic.

If your app has adopted IceCream, feel free to raise a PR to add to this page.

Donation

Crypto currency donation is the best. Even 0.01bTC helps.

Bitcoin

14J7KCR2x1Csh52SpPAvMWRh9EyNX5kxhE

Lisk

Lisk is my preferred crypto currency.

Lisk Deposit Address: 10081270051711082114L

Reference

License

IceCream is available under the MIT license. See the LICENSE file for more info.