Nick Harris

CloudKit + Core Data + NSOperations – Conclusions

with 11 comments

This is post four of four about CloudKit syncing with Core Data. The original post is here. Sample code is here. You’ll need to enable CloudKit and other entitlements in your own environment to get it to work correctly.


The previous posts includes a ton of code. You can see all of it by getting the project from BitBucket. In this post I’ll highlight what I liked and what I didn’t like. I learned a ton while writing it and would again urge you to heed my warning in the first post about it being unpolished and incomplete. 


CloudKit is incredibly powerful. Once I started really diving in I could tell it was thoughtfully created to support almost any type of app someone would want to create. Getting started was relatively easy and the more I learned I think the architectural decisions about how to get the most out of it became easier. Having pre-made NSOperations that handle all of the networking is very nice, even though I found myself subclassing them. Subscriptions are also incredibly powerful for getting any kind of push notifications and background fetching an app might need.

What I don’t like is that it is so generically built – its a strength and a weakness. From my time playing around and researching I didn’t find any real good best practices guidance which made all of the different ways of utilizing it harder to figure out (and I still think I’m wrong with some) as well as possible edge cases I never thought of.

You’re also betting a lot of usability of your app on your users having CloudKit enabled and having enough storage for your app to function appropriately. Using error codes you can build around that and appropriately inform your users of the problem, but they’re more then likely going to blame you instead of Apple. A casual user who paid $10, $20 maybe even $50 for a productivity app but was then prompted to pony up more money to Apple to make it work is a support nightmare.

I also don’t like that its unknown how Apple will handle changes they need to make to keep CloudKit going forward while handling backward compatibility. Its completely reasonable to think that the next version of CloudKit could deprecate all of the NSOperatoins I’m using in favor of new ones that handle problems they may be having server side. It may not be a big deal to refactor, depending how big the changes are, but that’s still a risk that is out of my hands.

The last thing that concerns me is how I would transfer a users private data to another backend system should I ever need to. The device would have to somehow do this at the great expense of the user experience. Imagine running an app for the first time after it updated in the background and it tells you it needs an hour of processing and all of your bandwidth to transfer the data somewhere else. This exact problem came up as my time on Glassboard was ending. The pricing of Azure SQL Server instances was dropping and the code we were using to support Table storage was beginning to show cracks. We didn’t do this but we could have spun up our new SQL instance and a background instance to slowly move our data from Tables to SQL. Our server code could make the process much more seamless to our users then what I would envision with CloudKit.

That being said, for me personally I would prefer a custom backend. I’m probably more biased then most iOS or Mac developers though since I’ve built a few on my own and worked on a handful of others throughout my career. I’ve built them in Java, Node.JS, C# and even straight JavaScript and classic asp pages years ago. I actually miss working on them. Performance tuning a database and server instances is more interesting to me then tweaking auto layout constraints for a day to get an animation to look nice. Not that I don’t love when a app looks sleek when I show it off, but I’d prefer showing off response time improvements more.

For my side project though? I’ll go with CloudKit. I’m building it for myself so I can easily keep up with any changes without worrying about dealing with the support emails.

NSOperation Chaining

I’ve said it before and I’ll say it again. I LOVE NSOperations! Once I found the pattern for passing data I love chaining them even more. CloudKit’s dependencies between zones and records as well as fetching before modifying make NSOperation dependencies close to a no brainer. I also like how I can separate concerns, encapsulate better and have reusable blocks of code I can chain together in many different ways.

It reminds me of one of my last final exams in college where we needed to make a data transformation diagram and detailed writeup showing how we would process a big chuck of data into its many pieces. I wish I could remember what the actual problem we had to solve was but after taking all 2 hours on the final to write it up I promptly empty my brain of it. Someone on twitter mentioned that the approach also resembles monads in functional programming. Just judging from the wikipedia page I’d have to agree but I haven’t explored functional programming very much yet.


Frankly my love of Swift just keeps growing. The proof of concept uses protocols and enums heavily. I haven’t taken the time to figure out how I would have accomplished the same things in Objective-C but I’m certain I would like my Swift code better. With swift though I learned:

– I love power of Swift Sets. Having intersect and subtract methods is fantastic. 

– Swift higher order functions are also great. I use flatMap a ton in this code. I probably could have used filter and reduce more as well.

– Finding out I could do inline predicates to find the index of an object was a very happy surprise:

// do we have this record locally? We need to know so we can remove it from the changedCloudKitManagedObjects
if let index = changedCloudKitManagedObjects.indexOf( { $0.recordName == deletedServerRecordID.recordName } ) {


– Casting in Swift is powerful in “if let” statements but even better in flatMap. 

– Guard statements continue to be good for me as well though I found I used them much less in this code then my first attempts at Swift.

– I think Swift is much more readable then Objective-C at this point.

– I still hate retain cycles. Seriously. I hate them. Capture lists are nice and all but I hate the fact that I still have to think about memory management.

Series Conclusion

I hope these posts are helpful. Don’t use them as a blueprint for how to use CloudKit but rather a long winded explanation of one persons adventures. Any feedback would be greatly appreciated!

Written by Nick Harris

February 9, 2016 at 6:54 am

Posted in Uncategorized

11 Responses

Subscribe to comments with RSS.

  1. Since you chose to use the private database I was wondering why you didn’t just use CloudKit Core Data that does syncing automatically for you?


    March 30, 2016 at 10:10 pm

    • I think because iCloud CoreData is deprecated in iOS10 and there is no alternative from Apple.


      July 7, 2016 at 12:37 pm

      • Ha good one!


        July 7, 2016 at 12:54 pm

  2. Thank you very much for CloudKit + CoreData + NSOperations posts! Found them very helpful!


    July 30, 2016 at 10:32 pm

  3. Using your method, how do you handle CKAsset ? Every time you want to save the CKRecord into CoreData, the fileURL of the CKAsset is

    Anthony Kersuzan

    September 5, 2016 at 9:56 am

    • the fileURL of the CKAsset is uninitialized

      Anthony Kersuzan

      September 5, 2016 at 9:57 am

    • This code was just a proof of concept. It doesn’t handle CKAsset at all. As I’ve said in previous comments – I would encourage you to find a pattern that works best for your application.

      Nick Harris

      September 5, 2016 at 4:52 pm

  4. I want to sync my apps data with cloudkit but this is horror. It will take me days for my simple app… wtf Apple…?

    Matei Suica

    February 19, 2017 at 5:06 pm

  5. I have to compliment you on this series of articles. Very nicely written and well-thought out. I am disappointed to hear that you did take this all the way to a fully working framework. Do you know if anyone did? I’d hate to retrace old ground to get this working for my app.


    September 9, 2017 at 4:00 pm

  6. Did you ever experience any latency issues between writes and reads?

    In my app I need to fetch all records in a custom zone (~12) shortly after writing them to the private db. The operations are all synchronized via dependencies. The data written to the cloud via CKModifyRecordsOperation is there as seen in the dashboard and verified by correct results in the completion handler. My problem is that CKQueryOperation doesn’t return records just written. If somehow I delay the call to CKQueryOperation then it works. This almost sounds like there’s somekind of latency between writing and reading.

    I’ve reviewed all the documentation and other than the operation based dependency mechanism I see no way of synchronizing reads and writes.


    October 26, 2017 at 11:31 pm

  7. Thank you. This was a wonderful series!


    December 19, 2017 at 8:12 pm

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: