<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Andrew Bancroft</title>
    <description>The latest articles on Forem by Andrew Bancroft (@andrewcbancroft).</description>
    <link>https://forem.com/andrewcbancroft</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F178146%2F37620b17-f20e-41b1-ae6c-58c7bcdcbdf3.jpeg</url>
      <title>Forem: Andrew Bancroft</title>
      <link>https://forem.com/andrewcbancroft</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andrewcbancroft"/>
    <language>en</language>
    <item>
      <title>New Course - iOS 14 Getting Started</title>
      <dc:creator>Andrew Bancroft</dc:creator>
      <pubDate>Fri, 04 Dec 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/andrewcbancroft/ios-14-getting-started-4pb8</link>
      <guid>https://forem.com/andrewcbancroft/ios-14-getting-started-4pb8</guid>
      <description>&lt;p&gt;Developing for iOS is a valuable and in-demand skill, but if you haven’t developed in the Apple world before, it can be surprisingly different.&lt;/p&gt;

&lt;p&gt;In this course, iOS 14: Getting Started, you’ll quickly get up and running using Xcode 12, Swift 5, and SwiftUI to build great iOS apps and tap into the latest features in iOS 14.&lt;/p&gt;

&lt;p&gt;Resources &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://bit.ly/iOS14-getting-started"&gt;iOS 14 Getting Started&lt;/a&gt;&lt;a href="https://bit.ly/iOS14-getting-started"&gt;&lt;br&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5uPkJaWF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/images/social-assets/ios-14-getting-started.png" alt="iOS 14 Getting Started"&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Course Outline
&lt;/h1&gt;

&lt;p&gt;First, you’ll see the tools and learn how to create iOS apps with adaptive user interfaces that work on multiple devices.&lt;/p&gt;

&lt;p&gt;Next, you’ll learn how to manage iOS projects and define the building blocks of your own iOS applications.&lt;/p&gt;

&lt;p&gt;Finally, you’ll explore working with data-driven controls and understand navigation options.&lt;/p&gt;

&lt;p&gt;When you’re finished with this course, you’ll know current best practices, iOS architecture, and the most important ideas you need to feel comfortable bringing your developer skills into the iOS and Apple developer world.&lt;/p&gt;

&lt;h2&gt;
  
  
  1 – Preparing to Build iOS Applications
&lt;/h2&gt;

&lt;p&gt;Prepare to implement iOS apps by understanding what’s involved from a big picture standpoint.&lt;/p&gt;

&lt;p&gt;We begin at the beginning to bring you up to speed and set the foundation for the remainder of the course.&lt;/p&gt;

&lt;p&gt;Topics in this module include…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What You Need for Building iOS Apps&lt;/li&gt;
&lt;li&gt;Creating an iOS Project with Xcode&lt;/li&gt;
&lt;li&gt;Exploring an iOS Project&lt;/li&gt;
&lt;li&gt;How to Learn iOS&lt;/li&gt;
&lt;li&gt;The Night Watch Scenario&lt;/li&gt;
&lt;li&gt;Working with Xcode Projects&lt;/li&gt;
&lt;li&gt;Grasping the Basics of the Xcode Development Environment&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2 - Building Single View Applications
&lt;/h2&gt;

&lt;p&gt;Building single view applications is the starting point for most of us who are learning to build iOS apps because they allow us a simplified architecture that focuses on a single screen performing a single responsibility.&lt;/p&gt;

&lt;p&gt;Topics in this module include…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing to Build Single View Apps&lt;/li&gt;
&lt;li&gt;Understanding the SwiftUI Framework&lt;/li&gt;
&lt;li&gt;Understanding Views&lt;/li&gt;
&lt;li&gt;Combining and Laying out Views&lt;/li&gt;
&lt;li&gt;Understanding the SwiftUI Layout System&lt;/li&gt;
&lt;li&gt;Aligning and Positioning Views&lt;/li&gt;
&lt;li&gt;Customizing UI Appearance&lt;/li&gt;
&lt;li&gt;Developing a SwiftUI Mindset&lt;/li&gt;
&lt;li&gt;Using Icons and Symbols&lt;/li&gt;
&lt;li&gt;Managing Views with Groups&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3 - Creating Data-driven Lists
&lt;/h2&gt;

&lt;p&gt;Just about any day in which you use an iPhone or iPad for more than a few minutes, you’ll almost certainly end up in an app that uses a List View.&lt;/p&gt;

&lt;p&gt;It’s the most common way to show a structured, scrollable series of items, and List Views are a core competency for an iOS developer working in SwiftUI, so it’s the first complex control we dive into.&lt;/p&gt;

&lt;p&gt;Topics in this module include…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing to Work with Lists&lt;/li&gt;
&lt;li&gt;Understanding Lists&lt;/li&gt;
&lt;li&gt;Creating a List&lt;/li&gt;
&lt;li&gt;Controlling a List with Data&lt;/li&gt;
&lt;li&gt;Using ForEach to Supply List Content&lt;/li&gt;
&lt;li&gt;Adding Sections and Headings&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4 - Building iOS Apps with Multiple Screens
&lt;/h2&gt;

&lt;p&gt;Here I cover how to create apps multiple screens and how to think about and enable navigation between them.&lt;/p&gt;

&lt;p&gt;Topics in this module include…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defining Apps with Multiple Screens&lt;/li&gt;
&lt;li&gt;Implementing Navigation Views&lt;/li&gt;
&lt;li&gt;Adding Navigation to an Existing Project&lt;/li&gt;
&lt;li&gt;Extracting Reusable Subviews&lt;/li&gt;
&lt;li&gt;Creating a Tabbed Application&lt;/li&gt;
&lt;li&gt;Recapping Multi-view Applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5 - Adding Behavior and Working With Data
&lt;/h2&gt;

&lt;p&gt;The thing that makes an app come alive is the behavior we add, and the dynamic responses to that behavior that get reflected in the user interface.&lt;/p&gt;

&lt;p&gt;In any application, a user interface has one critical job: to accurately represent the &lt;strong&gt;data&lt;/strong&gt; of our application in what it displays on the screen.&lt;/p&gt;

&lt;p&gt;In SwiftUI, data and behavior go hand-in-hand, and I cover how to respond to user interaction in this module.&lt;/p&gt;

&lt;p&gt;Topics in this module include…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing to Add Basic Behavior&lt;/li&gt;
&lt;li&gt;Extending the Data Model&lt;/li&gt;
&lt;li&gt;Understanding the View Update Cycle in SwiftUI&lt;/li&gt;
&lt;li&gt;Adding Basic Behavior&lt;/li&gt;
&lt;li&gt;Connecting a Subview to a Parent View’s Data&lt;/li&gt;
&lt;li&gt;Using Classes as Data Models&lt;/li&gt;
&lt;li&gt;Sharing a Data Model through the SwiftUI Environment&lt;/li&gt;
&lt;li&gt;Bringing the Data Model and Behavior to the Night Watch App&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6 - Putting It All Together
&lt;/h2&gt;

&lt;p&gt;There’s nothing like practicing your skills in new contexts to refine them and solidify what you’ve learned.&lt;/p&gt;

&lt;p&gt;We go into some additional controls and techniques for building apps with SwiftUI before concluding the course.&lt;/p&gt;

&lt;p&gt;Topics in this module include…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applying What You’ve Learned&lt;/li&gt;
&lt;li&gt;Integrating the Extended Data Model&lt;/li&gt;
&lt;li&gt;Adding the Mark Complete Behavior&lt;/li&gt;
&lt;li&gt;Adding a Toolbar and Toggle Control&lt;/li&gt;
&lt;li&gt;Implementing Swipe and Move Actions for a List&lt;/li&gt;
&lt;li&gt;Resetting the List&lt;/li&gt;
&lt;li&gt;Showing an Alert&lt;/li&gt;
&lt;li&gt;Creating an Adaptive UI&lt;/li&gt;
&lt;li&gt;Adding and Customizing Layout Variations&lt;/li&gt;
&lt;li&gt;Getting Ready for the App Store&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7 - Publishing to the App Store
&lt;/h2&gt;

&lt;p&gt;Finishing an app and getting it out the door to your users is one of the best feelings in the world.&lt;/p&gt;

&lt;p&gt;Beyond the emotional aspect of publishing an app though, more and more employers want to see job candidates who have published at least one app to the App Store.&lt;/p&gt;

&lt;p&gt;So in this final module, I complete the journey by setting you up to get an app into the App Store and bolster your resume!&lt;/p&gt;

&lt;p&gt;Topics in this module include…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing to Publish Your App&lt;/li&gt;
&lt;li&gt;Adding Images and App Icons&lt;/li&gt;
&lt;li&gt;Responding to Dark Mode&lt;/li&gt;
&lt;li&gt;Creating an iOS App Launch Screen&lt;/li&gt;
&lt;li&gt;Submitting an App for Review&lt;/li&gt;
&lt;li&gt;Continuing Your iOS Developer Journey&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Feedback Welcome!
&lt;/h1&gt;

&lt;p&gt;From the beginning my unwavering goal is to help you filter the noise and learn as efficiently as possible. My hope is that this course benefits you in your iOS development career!&lt;/p&gt;

&lt;p&gt;I welcome feedback on this course, and on other iOS development courses you might be interested in seeing in the Pluralsight library. Happy learning!&lt;/p&gt;

</description>
      <category>swift</category>
      <category>swiftui</category>
      <category>ios</category>
      <category>iosdev</category>
    </item>
    <item>
      <title>Implementing In-App Purchases on iOS</title>
      <dc:creator>Andrew Bancroft</dc:creator>
      <pubDate>Wed, 10 Jun 2020 10:48:21 +0000</pubDate>
      <link>https://forem.com/andrewcbancroft/implementing-in-app-purchases-on-ios-1ej5</link>
      <guid>https://forem.com/andrewcbancroft/implementing-in-app-purchases-on-ios-1ej5</guid>
      <description>&lt;p&gt;Monetizing apps is challenging. In this course, &lt;a href="https://bit.ly/implementing-in-app-purchases-ios"&gt;Implementing In-App Purchases on iOS&lt;/a&gt;, you’ll learn to offer digital products and services directly within your app as in-app purchases. &lt;/p&gt;

&lt;h1&gt;
  
  
  Course Outline
&lt;/h1&gt;

&lt;p&gt;First, you’ll explore how to translate business requirements into digital products and configure them in App Store Connect and Xcode. &lt;/p&gt;

&lt;p&gt;Next, you’ll discover how to build and test a store within your app using StoreKit. &lt;/p&gt;

&lt;p&gt;Finally, you’ll learn how to make sure purchases made within your app are authentic, and unlock content that’s been purchased by your users. &lt;/p&gt;

&lt;p&gt;When you’re finished with this course, you’ll have the skills and knowledge needed to implement in-app purchases on iOS!&lt;/p&gt;

&lt;h2&gt;
  
  
  1 – Preparing to Implement In-App Purchases
&lt;/h2&gt;

&lt;p&gt;Prepare to implement in-app purchases by understanding what’s involved from a big picture standpoint.&lt;/p&gt;

&lt;p&gt;You will learn to configure digital products in App Store Connect and Xcode to kick off your in-app purchase learning adventure.&lt;/p&gt;

&lt;p&gt;Topics in this module include...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Perks (And the Work) Ahead of You&lt;/li&gt;
&lt;li&gt;First Things First - Checking off the Prerequisites&lt;/li&gt;
&lt;li&gt;Matching Product Types to Business Requirements&lt;/li&gt;
&lt;li&gt;Setting Up Products in App Store Connect&lt;/li&gt;
&lt;li&gt;Setting Up an Auto-Renewable Subscription&lt;/li&gt;
&lt;li&gt;Configuring an Xcode Project for In-App Purchases&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2 – Building In-App Purchase Functionality with StoreKit
&lt;/h2&gt;

&lt;p&gt;The focus of this module is on the StoreKit APIs for working with digital products and App Store Connect.&lt;/p&gt;

&lt;p&gt;You will learn to build and test a fully-working store view that will support in-app purchases.  &lt;/p&gt;

&lt;p&gt;Topics in this module include...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using StoreKit to Build In-App Purchase Functionality: A Roadmap&lt;/li&gt;
&lt;li&gt;Retrieving a Set of Products for Purchase from the App Store&lt;/li&gt;
&lt;li&gt;Displaying Products in a User Interface&lt;/li&gt;
&lt;li&gt;Implementing a “Buy” Button&lt;/li&gt;
&lt;li&gt;Preparing to Test Purchases by Setting up a Sandbox Tester Account&lt;/li&gt;
&lt;li&gt;Making Test Purchases&lt;/li&gt;
&lt;li&gt;Implementing a “Restore Purchases” Button&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3 – Protecting Your Revenue by Verifying Purchase Authenticity
&lt;/h2&gt;

&lt;p&gt;After all your hard work to implement in-app purchases, how awful would it be if malicious users &lt;em&gt;stole&lt;/em&gt; the content you've labored to create?&lt;/p&gt;

&lt;p&gt;In this module, you will learn to implement measures to protect revenue generated through in-app purchases by validating App Store receipts.&lt;/p&gt;

&lt;p&gt;Receipt validation is a notoriously burdensome hassle. But it doesn't have to be!&lt;/p&gt;

&lt;p&gt;I will teach you how to implement server-side receipt validation from end-to-end with &lt;em&gt;no&lt;/em&gt; third-party libraries, &lt;em&gt;no&lt;/em&gt; complicated server setup, and &lt;em&gt;no&lt;/em&gt; platform-specific proprietary tools.&lt;/p&gt;

&lt;p&gt;Here's the roadmap of topics incluced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying Purchase Authenticity by Validating App Store Receipts&lt;/li&gt;
&lt;li&gt;Weighing Strategies for Receipt Validation&lt;/li&gt;
&lt;li&gt;Charting the Course for Server-side Receipt Validation&lt;/li&gt;
&lt;li&gt;Sending the Receipt from Your App to Your Server&lt;/li&gt;
&lt;li&gt;Writing Server-side Code to Forward the Receipt to the App Store for Validation&lt;/li&gt;
&lt;li&gt;Handling the Response from the App Store on Your Server&lt;/li&gt;
&lt;li&gt;Accounting for the Sandbox Environment on Your Server&lt;/li&gt;
&lt;li&gt;Handling the Response from Your Server in Your App&lt;/li&gt;
&lt;li&gt;The Case of the Missing Receipt: Requesting a Refresh&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4 – Unlocking Purchased Content
&lt;/h2&gt;

&lt;p&gt;After a user makes a valid purchase, you've got to unlock the content they legitimately bought!&lt;/p&gt;

&lt;p&gt;Each product type has its own nuances for how to unlock and provide the associated content though. &lt;/p&gt;

&lt;p&gt;What do you need to think about, and what code do you need to write to make it happen?&lt;/p&gt;

&lt;p&gt;To find out, you will explore these topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analyzing Content-providing Logic by Product Type&lt;/li&gt;
&lt;li&gt;Persisting Purchased Products Securely&lt;/li&gt;
&lt;li&gt;Using the iOS Keychain&lt;/li&gt;
&lt;li&gt;Keeping Track of Consumable Product Inventory&lt;/li&gt;
&lt;li&gt;Managing Non-Renewing Subscriptions&lt;/li&gt;
&lt;li&gt;Synchronizing Purchases Across Devices&lt;/li&gt;
&lt;li&gt;Handling Auto-Renewable Subscriptions&lt;/li&gt;
&lt;li&gt;Saving Non-Consumable Transactions&lt;/li&gt;
&lt;li&gt;Preparing for App Store Review&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Feedback Welcome!
&lt;/h1&gt;

&lt;p&gt;From the beginning I set out to make the course I wish &lt;em&gt;I&lt;/em&gt; had when I started learning to implement in-app purchases for &lt;em&gt;my&lt;/em&gt; apps.  My unwavering goal is to help you filter the noise and learn as efficiently as possible.  My hope is that this course benefits you in your iOS development career!&lt;/p&gt;

&lt;p&gt;I welcome feedback on this course, and on other iOS development courses you might be interested in seeing in the Pluralsight library. Happy learning!&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
    </item>
    <item>
      <title>Getting Started With NSPersistentCloudKitContainer</title>
      <dc:creator>Andrew Bancroft</dc:creator>
      <pubDate>Tue, 11 Jun 2019 04:40:54 +0000</pubDate>
      <link>https://forem.com/andrewcbancroft/getting-started-with-nspersistentcloudkitcontainer-5c73</link>
      <guid>https://forem.com/andrewcbancroft/getting-started-with-nspersistentcloudkitcontainer-5c73</guid>
      <description>&lt;h2&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’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’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’s the project I wish I had for referencing the basics…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="https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud"&gt;Apple’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 – I hope it helps!&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/andrewcbancroft/BlogIdeaList"&gt;Blog Idea List Example Xcode Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/videos/play/wwdc2019/202"&gt;Using Core Data With CloudKit - WWDC 2019 Session 202&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&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;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rrCG8btV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/enable-core-data-cloudkit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rrCG8btV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/enable-core-data-cloudkit.png" alt="Enable Core Data and CloudKit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&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’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’s important to check the CloudKit box when you create your app).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5tjD1UQY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/nspersistentcloudkitcontainer-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5tjD1UQY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/nspersistentcloudkitcontainer-code.png" alt="NSPersistentCloudKitContainer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What About Existing Apps?
&lt;/h3&gt;

&lt;p&gt;If you’ve got an existing app that’s using a “regular” &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’re not using &lt;code&gt;NSPersistentContainer&lt;/code&gt; with your app yet, &lt;a href="https://dev.to/andrewcbancroft/using-an-existing-sqlite-store-with-nspersistentcontainer-1o09-temp-slug-1652245"&gt;my guide on how to migrate&lt;/a&gt; may be of help!&lt;/p&gt;

&lt;h3&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&gt;
  
  
  Add iCloud + CloudKit
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MCuh9j7B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/add-icloud.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MCuh9j7B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/add-icloud.gif" alt="Add iCloud with CloudKit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Add Background Modes + Remote Notifications
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cP9gBxbr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/add-background-modes.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cP9gBxbr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/add-background-modes.gif" alt="Add Background Modes with Remote Notifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&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&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…yet. This is a setting you can toggle, but the default behavior is to “lazily” create the schema as people create objects and save them to your persistent store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MVa1VqT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/empty-schema.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MVa1VqT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/empty-schema.gif" alt="Empty Schema"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&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’s theme is “saving a list of blog ideas”, 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&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;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l-rHrM32--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/user-interface.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l-rHrM32--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/user-interface.png" alt="User Interface"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&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;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---0-w38ZY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/data-model.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---0-w38ZY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/data-model.png" alt="BlogIdea Data Model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No relationships or extra configuration options… 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="highlight"&gt;&lt;pre class="highlight swift"&gt;&lt;code&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;BlogIdea&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSManagedObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;@NSManaged&lt;/span&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;ideaTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
  &lt;span class="kd"&gt;@NSManaged&lt;/span&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;ideaDescription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;entityName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"BlogIdea"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&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;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight swift"&gt;&lt;code&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;MainViewController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIViewController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
   &lt;span class="kt"&gt;NSFetchedResultsControllerDelegate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
   &lt;span class="kt"&gt;UITableViewDataSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
   &lt;span class="kt"&gt;UITableViewDelegate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Responsible for listing out BlogIdeas in a table view&lt;/span&gt;

   &lt;span class="c1"&gt;// Holds a reference to an NSManagedObjectContext instance&lt;/span&gt;
   &lt;span class="c1"&gt;// which gets initialized in the SceneDelegate.swift file&lt;/span&gt;
   &lt;span class="c1"&gt;// and passed to this view controller when the scene gets "connected"&lt;/span&gt;

   &lt;span class="c1"&gt;// Uses NSFetchedResultsController to keep the table view in sync&lt;/span&gt;
   &lt;span class="c1"&gt;// with the Core Data managed object context&lt;/span&gt;

   &lt;span class="c1"&gt;// Implements swipe-to-delete with delete confirmation&lt;/span&gt;

   &lt;span class="c1"&gt;// Navigates to editor when someone taps on a table view row&lt;/span&gt;
   &lt;span class="c1"&gt;// and passes its NSManagedObjectContext instance along&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;BlogIdeaEditorViewController&lt;/strong&gt;&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight swift"&gt;&lt;code&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;BlogIdeaEditorViewController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIViewController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Responsible for creating new BlogIdeas&lt;/span&gt;

  &lt;span class="c1"&gt;// Holds a reference to an NSManagedObjectContext instance&lt;/span&gt;
  &lt;span class="c1"&gt;// which gets passed along in MainViewController's prepare for segue method&lt;/span&gt;

  &lt;span class="c1"&gt;// Able to edit existing BlogIdeas&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&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…things…don’t…seem to be working…&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/DLAwrSCl3Cc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;…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… nope. Thankfully it’s an “easy” fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflecting Changes in the UI
&lt;/h2&gt;

&lt;p&gt;Wherever you access your app’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;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight swift"&gt;&lt;code&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;willConnectTo&lt;/span&gt; &lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UISceneSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="nv"&gt;connectionOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;ConnectionOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.&lt;/span&gt;
   &lt;span class="c1"&gt;// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.&lt;/span&gt;
   &lt;span class="c1"&gt;// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).&lt;/span&gt;
   &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scene&lt;/span&gt; &lt;span class="k"&gt;as?&lt;/span&gt; &lt;span class="kt"&gt;UIWindowScene&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;navigationController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rootViewController&lt;/span&gt; &lt;span class="k"&gt;as!&lt;/span&gt; &lt;span class="kt"&gt;UINavigationController&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;mainVC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;navigationController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;viewControllers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as!&lt;/span&gt; &lt;span class="kt"&gt;MainViewController&lt;/span&gt;

   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;viewContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UIApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delegate&lt;/span&gt; &lt;span class="k"&gt;as!&lt;/span&gt; &lt;span class="kt"&gt;AppDelegate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;persistentContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;viewContext&lt;/span&gt;
   &lt;span class="n"&gt;viewContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;automaticallyMergesChangesFromParent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

   &lt;span class="n"&gt;mainVC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;managedObjectContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;viewContext&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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…&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&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;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5zujjJLw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/revisit-schema.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5zujjJLw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/revisit-schema.png" alt="Revisiting the Schema"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where’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’t find any.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;That’s because Apple fully manages a hidden Zone for your Core Data + CloudKit data. It was veeeery briefly mentioned in the &lt;a href="https://developer.apple.com/videos/play/wwdc2019/202"&gt;WWDC 2019 presentation&lt;/a&gt; (right about 10:50 if you’re watching).&lt;/p&gt;

&lt;h2&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="https://github.com/andrewcbancroft/BlogIdeaList"&gt;GitHub repo&lt;/a&gt;, leave a comment, or &lt;a href="https://twitter.com/andrewcbancroft"&gt;@ me on Twitter&lt;/a&gt; to continue the conversation from here!&lt;/p&gt;

</description>
      <category>swift</category>
      <category>coredata</category>
      <category>cloudkit</category>
      <category>ios13</category>
    </item>
    <item>
      <title>First Impressions of NSPersistentCloudKitContainer</title>
      <dc:creator>Andrew Bancroft</dc:creator>
      <pubDate>Thu, 06 Jun 2019 04:40:54 +0000</pubDate>
      <link>https://forem.com/andrewcbancroft/first-impressions-of-nspersistentcloudkitcontainer-2a2d</link>
      <guid>https://forem.com/andrewcbancroft/first-impressions-of-nspersistentcloudkitcontainer-2a2d</guid>
      <description>&lt;p&gt;Resources&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/videos/play/wwdc2019/202"&gt;Using Core Data With CloudKit - WWDC 2019 Session 202&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud"&gt;Sample Project from Apple&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How NSPersistentCloudKitContainer Helps
&lt;/h2&gt;

&lt;p&gt;I suppose the first question everyone should ask is, “What’s the big deal? How does &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; even help me?”&lt;/p&gt;

&lt;p&gt;I noted at least &lt;strong&gt;three huge wins&lt;/strong&gt; from the &lt;a href="https://developer.apple.com/videos/play/wwdc2019/202"&gt;WWDC 2019 session&lt;/a&gt;. Ask yourself…&lt;/p&gt;

&lt;p&gt;1) “Do I want to figure out how to retrieve data from CloudKit and merge it with my local Core Data persistent store on my own?” – No? Me either. 😃&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; handles making a local replica of your app’s CloudKit data.&lt;/p&gt;

&lt;p&gt;2) “Do I want to implement synchronization schedluing and all the error handling that comes with CloudKit?” – I &lt;em&gt;definitely&lt;/em&gt; don’t…&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; handles scheduling CloudKit operations, and takes your &lt;code&gt;// handle errors&lt;/code&gt; placeholder code (👀) and actually implements it the right way internally. #sweet&lt;/p&gt;

&lt;p&gt;3) “Do I want to map between &lt;code&gt;NSManagedObjects&lt;/code&gt; and &lt;code&gt;CKRecords&lt;/code&gt; by hand?” – Not if that could be automagic!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; handles transforming your &lt;code&gt;NSManagedObjects&lt;/code&gt; into &lt;code&gt;CKRecords&lt;/code&gt; as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exciting Times
&lt;/h2&gt;

&lt;p&gt;Apple did a lot of work to &lt;strong&gt;encapsulate a very common set of code patterns&lt;/strong&gt; that were necessary for implementing an app with Core Data and CloudKit.&lt;/p&gt;

&lt;p&gt;They claim to be able to &lt;strong&gt;save us thousands of lines of code&lt;/strong&gt; (and I believe it!).&lt;/p&gt;

&lt;p&gt;I have an app that uses Core Data locally. I’ve been wanting to enable CloudKit on, so that data is synced across my users’ devices. Every time I think about what it’ll take to get the Core Data pieces talking the on the same wavelength as the CloudKit pieces, I just dread the inevitable headache that would ensue. So I run away. 😬&lt;/p&gt;

&lt;p&gt;My hope is to see what it’s like to enable &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; with that existing app. I’ll be sure to document the journey!&lt;/p&gt;

&lt;h1&gt;
  
  
  Dipping a Toe In
&lt;/h1&gt;

&lt;p&gt;Just a couple of tidbits about the setup process for getting started with this new class…&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling Core Data + CloudKit
&lt;/h2&gt;

&lt;p&gt;While it’s not &lt;em&gt;absolutely&lt;/em&gt; required to check these checkboxes, Xcode will provide you with some of the boilerplate code necessary for working with Core Data and CloudKit &lt;strong&gt;together&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k4KZe9Jy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/first-impressions-of-nspersistentcloudkitcontainer/enable-coredata-cloudkit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k4KZe9Jy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/first-impressions-of-nspersistentcloudkitcontainer/enable-coredata-cloudkit.png" alt="Check Use Core Data + CloudKit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Point
&lt;/h2&gt;

&lt;p&gt;Xcode generates some code in your AppDelegate.swift file to initialize the Core Data Stack, only this time, instead of a standard &lt;code&gt;NSPersistentContainer&lt;/code&gt;, it initializes the new &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight swift"&gt;&lt;code&gt; &lt;span class="kd"&gt;lazy&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;persistentContainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSPersistentCloudKitContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSPersistentCloudKitContainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"NSPersistentCloudKitContainer_First_Steps"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadPersistentStores&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;completionHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storeDescription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;NSError&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Replace this implementation with code to handle the error appropriately.&lt;/span&gt;
   &lt;span class="nf"&gt;fatalError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unresolved error &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userInfo&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;
   &lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Not Ready Yet (more to enable)
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Enable CloudKit Capability
&lt;/h4&gt;

&lt;p&gt;Since you’re working with CloudKit in this scenario, you still need to &lt;em&gt;enable&lt;/em&gt; CloudKit so that your app has the appropriate &lt;strong&gt;entitlements&lt;/strong&gt; , and so that your app’s &lt;strong&gt;CloudKit container&lt;/strong&gt; gets created in iCloud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7uwrPusB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/first-impressions-of-nspersistentcloudkitcontainer/enable-icloud.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7uwrPusB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/first-impressions-of-nspersistentcloudkitcontainer/enable-icloud.gif" alt="Enable iCloud"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Enable Remote Notifications
&lt;/h4&gt;

&lt;p&gt;CloudKit also uses Push Notifications to alert your app to data changes coming in from other devices. To get these notifications, you need to enable the Remote Notifications capability for your app as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---7mzi-7w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/first-impressions-of-nspersistentcloudkitcontainer/enable-remote-notifications.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---7mzi-7w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/data-persistence/first-impressions-of-nspersistentcloudkitcontainer/enable-remote-notifications.gif" alt="Enable Remote Notifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;When it comes to learning what to do next, &lt;a href="https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud"&gt;Apple has provided a sample project&lt;/a&gt; that I hope to examine and take apart.&lt;/p&gt;

&lt;p&gt;More to come!&lt;/p&gt;

</description>
      <category>swift</category>
      <category>coredata</category>
      <category>cloudkit</category>
      <category>ios13</category>
    </item>
    <item>
      <title>SwiftUI is Declarative.  What Does That Mean?</title>
      <dc:creator>Andrew Bancroft</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:11:48 +0000</pubDate>
      <link>https://forem.com/andrewcbancroft/swiftui-is-declarative-what-does-that-mean-4eek</link>
      <guid>https://forem.com/andrewcbancroft/swiftui-is-declarative-what-does-that-mean-4eek</guid>
      <description>&lt;p&gt;“Declarative” is one of Swift UI’s four core principles.&lt;/p&gt;

&lt;p&gt;Aside from taking for granted that declarative is just “better” than &lt;em&gt;whatever else&lt;/em&gt;, how about a visual to understand the declarative way of thinking?&lt;/p&gt;

&lt;p&gt;Imagine yourself in a restaurant (sit-down or fast food, whichever).&lt;/p&gt;

&lt;p&gt;When you want a burger, which best describes what you do?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LWNAxYuh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/ui-work/swiftui-what-does-declarative-mean/burger-imperative.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LWNAxYuh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/ui-work/swiftui-what-does-declarative-mean/burger-imperative.png" alt="Burger Imperative"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HrA_S0VY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/ui-work/swiftui-what-does-declarative-mean/burger-declarative.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HrA_S0VY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/ui-work/swiftui-what-does-declarative-mean/burger-declarative.png" alt="Burger Declarative"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Saying &lt;strong&gt;what&lt;/strong&gt; you want (aka, being “declarative”) is what the most probable thing you’d do in a restaurant.&lt;/p&gt;

&lt;p&gt;That’s exactly the recipe you use when you’re working with SwiftUI.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uBU71x4E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/ui-work/swiftui-what-does-declarative-mean/burger-declarative-animation.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uBU71x4E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.andrewcbancroft.com/blog/ios-development/ui-work/swiftui-what-does-declarative-mean/burger-declarative-animation.gif" alt="Burger Declarative Animation"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swiftui</category>
      <category>swift</category>
      <category>ios</category>
    </item>
  </channel>
</rss>
