Timering

Purp

SyncKit tutorial - CloudKit with CoreData IOS10, Obj-C

This Tutorial shows you SyncKit, a great Solution for syncing your data using CloudKit between devices instead of iCloud Drive with Core Data, because of Core Data stores with ubiquity options have been deprecated. I’m going to create a simple model, where companies have departments and employees are in departments. I’ll import at launch CoreDataDefaults, exactly 5 Companies. After that I’m going to add new departments and employees too. With a Sync button, I will sync these Data with CloudKit.
Because of I import companies at first launch, if the user deletes the app, and later install it again, these will duplicate. Avoid this, I’m going to use QSPrimaryKey identifying objects, so if the Name of the Company already exists, that will be not synced again, that will be not duplicate neither in CloudKit nor local.

Steps

  1. Create CoreData Model
  2. Import Default Data at Launch, and fetch them in ViewDidLoad
  3. Create UIButton IBOutlets and IBActions to create Departments, Employees, and start Sync
  4. Create new Department and Employee Data 
  5. Set CloudKit available at the App and check if iCloud enabled by User
  6. Implement SyncKit
  7. Call Sync when the button clicked 
  8. Run the Application and Test the Results
  9. Test Deduplication
  10. Test 2 Device sync
  11. Download from Github

Video

1. Create CoreData Model

First of all you need to create this or a similar CoreData Model. You have to avoid many-to-many relationships, if you want to use CloudKit. For other warnings please check the Readme of SyncKit! For CoreData Tutorials click here!

1.1. Create a new project with Podfile.

Create a new Single View project with CoreData. Check AppDelegate.m, it must have Core Data stack.
Create a Podfile with SnycKit. Check this beginner tutorial for Cocoapods.
For SyncKit use in the Podfile what you find for version in the Readme on Git, or if you want to use QSPrimaryKey as an ObjectIdentifier to avoid duplication in CloudKit, you should update SyncKit pod for 0.3.1 version

Install pod, and now you can open the workspace and start to work.

1.2. Create CoreData Entities and attributes.

Create these attributes, and relationships. Pay attention for the To One and To Many relationships (Department —> Company relationship is To One, but company —> Department is To Many). I am using now Nullify as delete rule. (you can learn more about CoreData basics and Delete Rules here).

SyncKit tutorial 2 CloudKit IOS 10 Core Data

SyncKit tutorial 3 CloudKit IOS 10 Core Data

SyncKit tutorial 4 CloudKit IOS 10 Core Data

SyncKit tutorial 5 CloudKit IOS 10 Core Data

1.3 Subclass your model, and add QSPrimaryKey

Editor —> Create NSManagedObject Subclass…, select the Data Model, select all entities.
In you Companies+CoreDataClass.h add QSPrimaryKey Protocol:
And in Companies+CoreDataClass.m return your primaryKey identifier as a NSString:

SyncKit tutorial 6 CloudKit IOS 10 Core Data

SyncKit tutorial 7 CloudKit IOS 10 Core Data

I use the name of the company, because they are always unique, so my primaryKey will be the “cName” property.

If you have problems with subclassing your Entities check 8.1 for solution. 

2. Import Default Data at Launch

We need to check, if this is a first launch, and if yes, we need to save the first 5 companies.

2.1 Check first launch

In AppDelegat.h add a FirstLaunched Bool property:
@property(nonatomic) BOOL FirstLaunched;
In ViewController.m in ViewWillAppear create an NSUserDefault for check the bool value for FirstLaunched, and if it is the first launch, set the bool YES and call a function named importCoreDataDefaults.

SyncKit tutorial 8 CloudKit IOS 10 Core Data

2.2 Synthesize AppDelegate ManagedObjectModel and ManagedObejctContext, and write over Core Data stack if it's necessary

2.3 Import Default Data & check it with fetch request

In ViewController.h create ManagedObjectContext and ManagedObjectModel, synthesize them in .m file. Import Companies+CoreDataProperties.h in ViewController.m file and create the first 5 company with properties, and save it in CoreData.
Create an Fetch Request Template in DataModel to fetch all company object in ViewDidLoad, so you can see the count of the companies in your Log.

SyncKit tutorial 9 CloudKit IOS 10 Core Data

3. Create UIButton IBOutlets and IBActions to create Departments, Employees, and start Sync

Create the buttons on the Storyboard the buttons and their properties and actions:

SyncKit tutorial 10 CloudKit IOS 10 Core Data

4. Create new Departments and Employees Data

Use this Code to create and save new Department and Employe Data if you click the Button. With NLog we can see them in log, so we don’t need to create TableViews and manage rows to check the data. Of course you will do it in your real App :)

4.1. Import the CoreDataProerties H file:

#import "Departments+CoreDataProperties.h"
#import "Employees+CoreDataProperties.h"

4.2. Create Fetch Request Template for Departments and Employees

SyncKit tutorial 11 CloudKit IOS 10 Core Data

4.3. In IBAction create NSFetchRequest from template ...

..to check the count of Departments/Employees, and after that you can create a new one with attribute, which depends on the count. You can list all objects of the array in log if you want to check not just the count of the objects.

SyncKit tutorial 12 CloudKit IOS 10 Core Data

5. Set CloudKit available at the App and check if iCloud enabled by User

5.1 Set iCloud on

At the Project Target in the Capabilities set iCloud on, and tick CloudKit. Better to use default container, which is the Application Bundle name. CloudKit containers can’t be deleted, so you should sure, that you are using a final bundle name for your App.

SyncKit tutorial 13 CloudKit IOS 10 Core Data

5.2 Implement iCloud functions

In AppDelegate DidFinishLaunchingWithOptions create a UserDefault with “iCloudEnabled” Dictionary. And call a function, which check, whether the user is signed in iCloud.

SyncKit tutorial 14 CloudKit IOS 10 Core Data

Implement the iCloud functions after the SaveContext method in AppDelegate.m. The first check, whether the user is signed in iCloud, the second checked, that iCloud is enabled by user on the device.

SyncKit tutorial 15 CloudKit IOS 10 Core Data

the code:

6. Implement SyncKit

Now you can implement SyncKit methods as you can read it.

6.1 import & delegate QSCoreDataChangeManager:

In AppDelegate.h file import & delegate QSCoreDataChangeManager:

#import <SyncKit/QSCloudKitSynchronizer+CoreData.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, QSCoreDataChangeManagerDelegate>

And Create a synchronizer property:
@property (nonatomic, strong) QSCloudKitSynchronizer *synchronizer;

6.2. Implement the SyncKit Synchronizer method 

I completed this method with the user iCloud availability control. Here you have to check the container name, which is very important, it must be the same as your CloudKit container, iCloud.com.maybeHereComapnyName.AppName.
And add the sync function, which call the synchronization, and at the end I call the companies fetch request, to check the companies count again. That will be important to check the deduplication after the second installation.

In AppDelegate.m implement:
changeManagerRequestsContextSave:
and changeManager didImportChanges:

6.3. Finally implement the QSCoreDataChangeManagerDelegate in AppDelegate.m

Here at did ImportChanges I check the companies count again.

7. Call Sync when the button clicked

In AppDelegate.h don’t forget the sync function:
-(void)sync;
After that you can call it from ViewController.m, when the Sync button clicked:

Now everything is ready to test!

8. Run the Application and Test the Results

Before start the test, open your CloudKit Dashboard (at Project Target —> Capabilities —>iCloud click on the CloudKit Dashboard button. You have to be logged in with your Apple Developer ID.
You will see this dashboard, without any Record Types or Records (just the default Users Record Types).

SyncKit tutorial 16 CloudKit IOS 10 Core Data

8.1 Start to run the App in Simulator or on Device.

If you have linker command failed with exit code 1 (use -v to see invocation) error because of symbol duplication in CoreDataClass files. You have to set Manual/None Codegen at the Entitiy instead of Class Definition. And the Global Space to Current Product Module if it's necessary.

SyncKit tutorial 161 CloudKit IOS 10 Core Data

SyncKit tutorial 162 CloudKit IOS 10 Core Data

After the first launch your log will notice you about the user iCloud account and availability, and about the first import.

SyncKit tutorial 17 CloudKit IOS 10 Core Data

If you click the Add Department button, in your log you will see, that you have 0 departments, and after that you saved the first one. Click it again, and you will see, now you have 1 department, and you added one more.

SyncKit tutorial 18 CloudKit IOS 10 Core Data

Click on Add Employees, and see the log. Now, if you have Companies, Departments, and Employees too. Click the Sync button. Now you can see the whole Sync process, how many records have been uploaded, downloaded, and how many companies you have.

SyncKit tutorial 20 CloudKit IOS 10 Core Data

Relaunch your CloudKit Dashboard, and you will see the Record Types.

SyncKit tutorial 21 CloudKit IOS 10 Core Data

You can run it again, and you can add more Departments, Employees, and you can Sync them again.
You will see, that the departmentsArray count is increasing.

SyncKit tutorial 22 CloudKit IOS 10 Core Data

9. Test Deduplication

9.1.Now you can Stop the App, Delete it from the device, and run again - this is a total new Launch! 

You can add again Departments, Employees, and you can Sync them. After your sync, you should see the Companies count stay just 5! (If you don’t use PrimaryKey, it will duplicate to 10).
Stop the App, and Run it Again! Just tap the Sync button, and after the “Add Department” button. Now you will see, that you have 5 departments and you add the 6th. Don’t tap the Sync button again, so in CloudKit stay 5 departments.

9.2 Now stop, and delete the App again. And Run. And now tap the Sync button first, and after the Department. 

You will see 5 departments, and you add the 6th again. Because you deleted the App, your 6th department, what you added before is disappeared, and stayed just those 5, which saved in CloudKit.

SyncKit tutorial 23 CloudKit IOS 10 Core Data

You will see in CloudKit Dashboard your Records too, the Companies stayed 5 after new App install with new import. And you can check the Record counts at Departments and Employees too.

SyncKit tutorial 24 CloudKit IOS 10 Core Data

10. Test 2 Device Synchronization

Run the App on your second Device(I’m using an old iPad with IOS9 which works great too ). First click Sync button. You will see, the 5 companies, and the whole Sync process.

SyncKit tutorial 25 CloudKit IOS 10 Core Data

Tap twice the Add Departments button. Now you have 7 departments, but just 5 synced, so tap Sync button.

SyncKit tutorial 26 CloudKit IOS 10 Core Data

After your synchronization, open the App on your first device (Run from Xcode to see log).
Tap first Sync button, and after that Add Department. You had on this device 5 synced and one more department, and now after you synced, you have 7 synced (5 from earlier, and 2 from the other device saved and synced) and 1 more department (not synced), and if you tap the Add Departments button, it shows you all 8 departments, and because of this button add a new one, you will see in log d1 saved, and 1 new insertion.

SyncKit tutorial 27 CloudKit IOS 10 Core Data

Download:

Download the Xcode template from Github.

NEXT

The next part of the series: later with further development of SyncKit. Migrations and Sharing. 

Share & Follow

If you would like to be notified of my new solutions, please subscribe to my Newsletter or my youtube channel and/ or follow me on Facebook or Twitter! Check Footer section for these opportunities!