<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>NSPersistentCloudKitContainer on Andrew Bancroft</title>
    <link>https://www.andrewcbancroft.com/tags/nspersistentcloudkitcontainer/</link>
    <description>Recent content about iOS development with Swift in NSPersistentCloudKitContainer  from Andrew Bancroft.</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 11 Jun 2019 04:40:54 +0000</lastBuildDate>
    
        <atom:link href="https://www.andrewcbancroft.com/tags/nspersistentcloudkitcontainer/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Getting Started With NSPersistentCloudKitContainer</title>
      <link>https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/</link>
      <pubDate>Tue, 11 Jun 2019 04:40:54 +0000</pubDate>
      
      <guid>https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/</guid>
      <description>&lt;h2 id=&#34;first-things-first&#34;&gt;First Things First&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In order to use &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; in your app, you need to be targeting iOS 13+.&lt;/li&gt;
&lt;li&gt;The CloudKit syncing portion only works on physical devices (not in the simulator).  That being the case, you&amp;rsquo;ll need two or more devices running the app and using the same iCloud account to fully test things out and make sure syncing and data merging behavior works as you&amp;rsquo;d expect it to.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal of this walkthrough is to provide you with a fully-working example of performing and synchronizing create, read, update, and delete operations using &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s the project I wish I had for referencing the basics&amp;hellip;something &lt;strong&gt;beyond&lt;/strong&gt; the out-of-the-box, saving a list of timestamps that comes pre-implemented with a Master-Detail app, but something &lt;strong&gt;less complicated&lt;/strong&gt; than &lt;a href=&#34;https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud&#34; rel=&#34;nofollow&#34;&gt;Apple&amp;rsquo;s example project&lt;/a&gt; which ends up having several relationships involved in the data model, extra features configured on the persistent container, etc.&lt;/p&gt;
&lt;p&gt;I offer it to you as reference as well &amp;ndash; I hope it helps!&lt;/p&gt;
&lt;p&gt;&lt;a name=&#34;resources&#34; class=&#34;jump-target&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;resources&#34;&gt;
&lt;div class=&#34;resources-header&#34;&gt;
Resources
&lt;/div&gt;
&lt;ul class=&#34;resources-content&#34;&gt;
&lt;li&gt;
&lt;i class=&#34;fas fa-file-code&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://github.com/andrewcbancroft/BlogIdeaList&#34;&gt; Blog Idea List Example Xcode Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;i class=&#34;fas fa-link&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2019/202&#34; rel=&#34;nofollow&#34;&gt;Using Core Data With CloudKit - WWDC 2019 Session 202&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;
&lt;p&gt;The easiest way to get stareted with &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; is to enable Core Data and CloudKit when you start your new project.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;enable-core-data-cloudkit.png&#34; alt=&#34;Enable Core Data and CloudKit&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-core-data--cloudkit-stack&#34;&gt;The Core Data + CloudKit Stack&lt;/h3&gt;
&lt;p&gt;Xcode provides the Core Data Stack code you need in the usual location: in the AppDelegate.swift file.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s one notable difference though.  Instead of initializing a normal &lt;code&gt;NSPersistentContainer&lt;/code&gt;, Xcode uses the new &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; (this is why it&amp;rsquo;s important to check the CloudKit box when you create your app).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;nspersistentcloudkitcontainer-code.png&#34; alt=&#34;NSPersistentCloudKitContainer&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;what-about-existing-apps&#34;&gt;What About Existing Apps?&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;ve got an existing app that&amp;rsquo;s using a &amp;ldquo;regular&amp;rdquo; &lt;code&gt;NSPersistentContainer&lt;/code&gt;, you can change it to &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; and continue on from there!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re not using &lt;code&gt;NSPersistentContainer&lt;/code&gt; with your app yet, &lt;a href=&#34;https://www.andrewcbancroft.com/2017/07/10/using-an-existing-sqlite-store-with-nspersistentcontainer/&#34;&gt;my guide on how to migrate&lt;/a&gt; may be of help!&lt;/p&gt;
&lt;h3 id=&#34;adding-capabilities&#34;&gt;Adding Capabilities&lt;/h3&gt;
&lt;p&gt;While Xcode auto-generates the Core Data + CloudKit stack for you, it does &lt;em&gt;not&lt;/em&gt; enable iCloud for you.&lt;/p&gt;
&lt;p&gt;To enable full functionality, you need to go to your &lt;strong&gt;Xcode project settings&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Then click on the &lt;strong&gt;Signing &amp;amp; Capabilities&lt;/strong&gt; section and add the &lt;strong&gt;iCloud&lt;/strong&gt; and &lt;strong&gt;Background Modes&lt;/strong&gt; capabilities.&lt;/p&gt;
&lt;p&gt;Check the &lt;strong&gt;CloudKit checkbox&lt;/strong&gt;, and the &lt;strong&gt;Remote Notifications checkbox&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&#34;add-icloud--cloudkit&#34;&gt;Add iCloud + CloudKit&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;add-icloud.gif&#34; alt=&#34;Add iCloud with CloudKit&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;add-background-modes--remote-notifications&#34;&gt;Add Background Modes + Remote Notifications&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;add-background-modes.gif&#34; alt=&#34;Add Background Modes with Remote Notifications&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;what-about-registering-for-remote-notifications&#34;&gt;What About Registering for Remote Notifications?&lt;/h3&gt;
&lt;p&gt;The beauty of &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; is that it handles all the work required to listen for and respond to remote notifications.&lt;/p&gt;
&lt;p&gt;This means that data saved locally on &lt;em&gt;one&lt;/em&gt; device gets pushed up to iCloud synced back down to &lt;em&gt;another&lt;/em&gt; device automatically.&lt;/p&gt;
&lt;h3 id=&#34;what-about-my-data-model-in-icloud&#34;&gt;What About My Data Model in iCloud?&lt;/h3&gt;
&lt;p&gt;When you enable the iCloud capability for your app, Xcode automatically creates a container for your app in the CloudKit Dashboard.&lt;/p&gt;
&lt;p&gt;It does &lt;em&gt;not&lt;/em&gt;, however, create a schema that matches your Core Data model&amp;hellip;yet.  This is a setting you can toggle, but the default behavior is to &lt;a href=&#34;#revisiting-the-icloud-schema&#34;&gt;&amp;ldquo;lazily&amp;rdquo; create the schema&lt;/a&gt; as people create objects and save them to your persistent store.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;empty-schema.gif&#34; alt=&#34;Empty Schema&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;walking-through-the-example-project&#34;&gt;Walking Through the Example Project&lt;/h2&gt;
&lt;p&gt;WWDC always gets the blog ideas flowing through my brain, so this little app&amp;rsquo;s theme is &amp;ldquo;saving a list of blog ideas&amp;rdquo;, both locally, and &lt;em&gt;across&lt;/em&gt; my devices using &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;user-interface&#34;&gt;User Interface&lt;/h3&gt;
&lt;p&gt;The user interfacde allows you to perform the essential operations of a data-driven app:  create, read, update, and delete objects.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;user-interface.png&#34; alt=&#34;User Interface&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;data-model&#34;&gt;Data Model&lt;/h3&gt;
&lt;p&gt;The data model for this is basic:  a single &lt;code&gt;BlogIdea&lt;/code&gt; Entity with two &lt;code&gt;String&lt;/code&gt; properties: &lt;code&gt;ideaTitle&lt;/code&gt; and &lt;code&gt;ideaDescription&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;data-model.png&#34; alt=&#34;BlogIdea Data Model&#34;&gt;&lt;/p&gt;
&lt;p&gt;No relationships or extra configuration options&amp;hellip; just one Entity to keep it a basic reference-able project.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;BlogIdea&lt;/code&gt; NSManagedObject subclass is implemented like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;BlogIdea&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NSManagedObject&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;@NSManaged&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ideaTitle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;@NSManaged&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ideaDescription&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;entityName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;BlogIdea&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;view-controllers&#34;&gt;View Controllers&lt;/h3&gt;
&lt;p&gt;There are two view controllers that come with this example:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MainViewController&lt;/strong&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MainViewController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;UIViewController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                            &lt;span class=&#34;n&#34;&gt;NSFetchedResultsControllerDelegate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                            &lt;span class=&#34;n&#34;&gt;UITableViewDataSource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                            &lt;span class=&#34;n&#34;&gt;UITableViewDelegate&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Responsible for listing out BlogIdeas in a table view&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Holds a reference to an NSManagedObjectContext instance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// which gets initialized in the SceneDelegate.swift file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// and passed to this view controller when the scene gets &amp;#34;connected&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Uses NSFetchedResultsController to keep the table view in sync&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// with the Core Data managed object context&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Implements swipe-to-delete with delete confirmation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Navigates to editor when someone taps on a table view row&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// and passes its NSManagedObjectContext instance along&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;strong&gt;BlogIdeaEditorViewController&lt;/strong&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;BlogIdeaEditorViewController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UIViewController&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Responsible for creating new BlogIdeas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Holds a reference to an NSManagedObjectContext instance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// which gets passed along in MainViewController&amp;#39;s prepare for segue method&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Able to edit existing BlogIdeas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;h2 id=&#34;understanding-the-default-sync-behavior&#34;&gt;Understanding the Default Sync Behavior&lt;/h2&gt;
&lt;p&gt;At this point no additional configuration has happened. The Core Data stack is the unmodified Xcode generated code, and the fetched results controller is hooked up to the managed object context for your app, ready to fetch Blog Ideas and help get them into the table view.&lt;/p&gt;
&lt;p&gt;If you open the project, build and run on two devices, and begin adding Blog Ideas, updating them, deleting them, etc. what happens?&lt;/p&gt;
&lt;p&gt;The first observation is that&amp;hellip;things&amp;hellip;don&amp;rsquo;t&amp;hellip;seem to be working&amp;hellip;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/DLAwrSCl3Cc&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&amp;hellip;At least not how I thought they would.&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;expected&lt;/em&gt; my Blog List view to automatically update in response to changes made on my other device, buuut&amp;hellip; nope.  Thankfully it&amp;rsquo;s an &amp;ldquo;easy&amp;rdquo; fix.&lt;/p&gt;
&lt;h2 id=&#34;reflecting-changes-in-the-ui&#34;&gt;Reflecting Changes in the UI&lt;/h2&gt;
&lt;p&gt;Wherever you access your app&amp;rsquo;s persistent CloudKit container to grab the &lt;code&gt;viewContext&lt;/code&gt;, you need to set the &lt;code&gt;automaticallyMergesChangesFromParent&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I initialize the container in the &lt;code&gt;SceneDelegate&lt;/code&gt;, so check out the code exerpt below to see where that gets set.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SceneDelegate.swift&lt;/strong&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;scene&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scene&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UIScene&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;willConnectTo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UISceneSession&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;options&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;connectionOptions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UIScene&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ConnectionOptions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;guard&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scene&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UIWindowScene&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;navigationController&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rootViewController&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UINavigationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mainVC&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;navigationController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewControllers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MainViewController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;viewContext&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UIApplication&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shared&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;delegate&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AppDelegate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;persistentContainer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;viewContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;automaticallyMergesChangesFromParent&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;mainVC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;managedObjectContext&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;viewContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Making this one-line change will enable the app (which is supported by &lt;code&gt;NSFetchedResultsController&lt;/code&gt;) to update the UI in response to remote data changes&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;eventually&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It can be slow (anywhere from 5 to 15 seconds).  But it will eventually update.&lt;/p&gt;
&lt;h2 id=&#34;revisiting-the-icloud-schema&#34;&gt;Revisiting the iCloud Schema&lt;/h2&gt;
&lt;p&gt;Once you save an object, the schema within the iCloud Dashboard will update to reflect the properties you designed in your Core Data Model.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;revisit-schema.png&#34; alt=&#34;Revisiting the Schema&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;wheres-my-data&#34;&gt;Where&amp;rsquo;s My Data?&lt;/h2&gt;
&lt;p&gt;If you attempt to query for BlogIdea records in any of the iCloud databases provisioned for your app, you won&amp;rsquo;t find any.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s because Apple fully manages a hidden Zone for your Core Data + CloudKit data. It was veeeery briefly mentioned in the &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2019/202&#34; rel=&#34;nofollow&#34;&gt;WWDC 2019 presentation&lt;/a&gt; (right about 10:50 if you&amp;rsquo;re watching).&lt;/p&gt;
&lt;h2 id=&#34;wrapping-up&#34;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;My hope was to provide you with a fully-working example of performing and synchronizing create, read, update, and delete operations using &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&#34;https://github.com/andrewcbancroft/BlogIdeaList&#34;&gt;GitHub repo&lt;/a&gt;, leave a comment, or &lt;a href=&#34;https://twitter.com/andrewcbancroft&#34;&gt;@ me on Twitter&lt;/a&gt; to continue the conversation from here!&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>