NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

Has anyone used the Xcode 12 template when you create an app using Core Data and CloudKit?

Forums > SwiftUI

Hi,

I'm a bit frustrated. I am trying to explore the idea of using Core Data and CloudKit to keep data in-sync across multiple iOS devices. So I opened up Xcode 12.4, created a new iOS project and made sure that "Use Core Data" and "Host in CloudKit" were enabled. This results in Xcode somewhat helpfully offering some template code to get me started (fantastic). And having gone through 100 Days Of SwiftUI and its introduction to Core Data this code (while somewhat different) is not completely new so I at least have some idea of what it is doing. It also resulted in a lot of stop signs popping up, but closing and reopening the project fixed that (this seems to have been all references to the "Item" entity in the .xcdatamodel that was generated when the project was created and something I also encountered when I was going through the 100 Days Of SwiftUI tutorial that covered Core Data so wasn't unexpected).

So I decided to just try it out and see what happens. The first thing is that in the preview, and the iOS simulator (or even on my iPod touch or iPad Pro) the buttons defined in the template for the ContentView don't show up. Rather difficult to test how things work when the add button won't appear. I'm somewhat surprised that it doesn't work right out of the box, but figured out that I can put the List into a NavigationView and that helps the Edit button to appear, but not the Add (+) button. Wrapped the buttons together under the .toolbar line in a HStack. Also added a navigationBarTitle just to make things look a bit better.

Now I build and run the app on my iPod touch and the add button is there, I can tap on it and it works to add an item (just the current date & time) to the list. Yay! If I close the app and reopen it, the added lines are still there. Yay! (again). So I'm really encouraged here that everything is just going to "work" from this point and I move on to the next thing. I disconnect my iPod touch, plug in my iPad Pro and build and run the app. There is the primary list view with my title and the Add (+) button and the Edit button and.... no data in the list.

I start to look around online to see if I can find out what is missing and I come across part of an answer. Apparently I have to select the project, go under Signing & Capabilities and add a couple of capabilities for iCloud and Background Modes. In the Background Mode I need to turn on "Remote notifications", and in the iCloud section I need to turn on CloudKit and... according to Apple's documentation that I found in my search... I need to "Under Containers, leave the selection as 'Use default container'." which is interesting, because there is no such option in Xcode 12. There is also an empty list under Containers and I can click the "+" button there but I have no idea what I'm supposed to type in there. And then the Apple documentation goes even further off into obscurity by referencing changes that need to be made in the AppDelegate.

I looked around online some more and all I seem to be able to find is tutorials or videos that are directly based on how things used to be. Some don't even bother to even explain the Signing & Capabilities stuff at all and just link to that same Apple developer page I already had found.

I am assuming that I do have to fill something into that Containers section for iCloud in Signing & Capabilities, but I don't know what. I'm assuming that there might be something I need to modify in Persistence.swift... I'm guessing perhaps changing line 36 to direct to something other than "/dev/null" for fileURLWithPath ? But again, I'm not really sure what. There might be other things as well?

Has anyone here actually gone through the template code provided by Xcode 12 for Core Data and CloudKit and figured this stuff out already or does anyone know of a tutorial or video somewhere that I might have missed that covers this and isn't based on options and files that no longer exist?

   

After more digging I found something online that suggested what I need to type in as a container would be a reverse domain (like the bundle identifier for my app) starting with "iCloud." So I tried that and what I entered showed up in the list in red. I then hit the little refresh button below the list and it turned black... and then it opened a second list with it showing up in red so I hit the refresh button under the second one and then it merged back to a single iCloud section and was black. So I deleted the previous app build on my iPod touch and iPad Pro. I connected my iPod touch and did a build and run. The app appears with nothing in the list. I hit the + button in the app a few times to add some date & time stamps. At this point I also noticed that Xcode is now reporting something that implies it is doing stuff with Core Data and iCloud. Well this is encouraging as that didn't happen before.

I then disconnected my iPod touch, connected my iPad Pro and did a build and run. The app appears... with nothing in the list??? I thought it was working. I force quit the app with a double-tap on home and swiping it up. I open the app again on the iPad... suddenly the items I added on the iPod touch do appear (yay!) I try this process several times adding and deleting various items on one device or the other. It seems there is no instant syncing. I can't delete an item on one device and watch it vanish from the other or add an item on one device and watch it magically appear on the other. It seems that if the app is still running in the foreground, or even if it is still running in the background and then reopened it just won't update. It seems that even if I force quit the app and open it that sometimes it won't update if I just made a change on the other device within the last minute or two or at least until I force quit the app a couple of times. That can't be right.

Is this behavior consistent with the template code Apple provides with Xcode 12.4 and it needs some changes to work in a more immediate fashion? Is this behavior unexpected and the result of me doing something else wrong? If I hadn't thought to try force quitting the app and reopening I'd probably still be sitting here thinking that it wasn't working at all.

   

I did more digging and finally found something. It appears the template Apple has in Xcode 12.4 for handling "Host in CloudKit" is missing some code in Persistence.swift that helps with updating things in a more timely fashion (and how it will manage the sync). I'm really surprised between this and the error in ContentView for the Edit and Add buttons that I previously mentioned. I would have thought Apple would have done better. Anyway... here is the code I found online that seems to fix it. I added this directly below the closing }) for container.loadPersistentStores(... that starts on line 38 in the Persistence.swift file:

        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        container.viewContext.automaticallyMergesChangesFromParent = true

The updating isn't instantaneous, but it is pretty decent (around 15 seconds or so in my testing here).

   

I'm surprised the ContentView didn't work out of the box. I created a project just like you did a few weeks ago and it worked well.

I did have to add the capabilities manually, like you mentioned, but after watching a few tutorials on cloudkit, I new that was a needed step.

I had tried doing the reverse, adding core data to an existing project, and ended up createing a new project with core data and moving my views from the old project into the new one. It worked pretty well for me.

Thanks for updating on adding those lines of code. I had noticed that updating from one the device to the other was taking way too long. I'll give that a try.

1      

Hacking with Swift is sponsored by Instabug

SPONSORED Catch bugs as soon as they happen and know exactly why a crash occurred. Instabug's SDK grabs all the logs they need to fix bugs, crashes and performance issues in minutes instead of days. Get screenshots, device details, network logs, repro steps, and tons of other critical insights needed to resolve issues and prioritize product backlogs straight from your dashboard. It only takes a minute to integrate!

Get started now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.