Part 8: A Quick App UI
This is probably the part I am least relaxed about doing in public as I really have no idea what I'm doing. :-)
I made a new CoreData SwiftUI project and essentially stole the guts of that to make it work in my app. All it has to do, really, is show a big list of All The Things. It was relatively easy for me to add Add+Delete functionality on iOS so that's what I did. iOS can create and delete Things, all the other platforms just show a read only list.
Environmental Context
The first step is making the shared context from our persistence controller available to the app. We do this through the SwiftUI environment.
Since there's no way to add any items for display yet, You can see above I added back the preview version of the PersistenceController
. Again this is just Apple's template code unchanged apart from adjustments for my own Entities.
It provides an in-memory, disposable context with 10 Things in it so we can
We can swap the app property from PersistenceController.preview
to PersistenceController.shared
when we're happy.
List Views
Next up I added two separate ListViews. The first is in AppShared
and added to both app targets because it works across Watch and Mac+TV+Phone and I called it SimpleListOfThingsView
It's dirt simple and just uses the environment context to fetch all the Things, sorted by oldest first, and displays them in a list.
Here's how it looks on a Mac, TV and Watch.
Nothing to write home about but it works.
Next we'll create the version for the iPhone. I've added this just to the Apps -> JustOneThing folder and just the app target as it's specific to the Phone app. Its just called ListOfThingsView
Again this is just lifted directly from the new project I made. The top of the View looks basically the same as the SimpleListOfThingsView
but it comes with the add and remove methods that Apple's template provided.
Here's the body. You can see the issue with using the CoreData entity directly since all its fields are optional I'm supplying default text everywhere for now. We'll fix that when we add a translation layer between our PersistentThing
class and our Thing
value type later.
The addItem
method just creates a PersistentThing
with no user input (Apple's sample unchanged).
and the deleteItems
machinery is unchanged.
I tried to get the swipe deletion working on the Mac but gave up as (like I've said) I really don't care about the app UI I just want to work on the widgets. Hence its just the iOS app that provides any kind of interaction.
On iOS the view looks like this and of course the edit button and swiping to delete works fine.
The last step it to use these two new views in the app. For that we make a change to the ContentView
to load the right view on the right platform.
At this point we can test out both views on all the various simulators and when we';re happy they work we can switch the PersistenceController
in the app from .preview
to .shared
and try it all out. If you sign into iCloud on the various platforms and simulators you should be able to create things on iPhone and see them appear on tv, Mac and watch.
One issue I have been unable to resolve is that it can take some time for a first run of an app to download its initial set of data from iCloud, leading me to believe it hadn't worked. I'd love some way to put up, if not a modal, then some kind of indicator that says "hold on while I do the first sync of data". But because it's all happening in the background and you're not supposed to care, there doesn't seem to be an easy way to be notified. (Happy to accept answers on a postcard).
Lets commit! It's under "Part 8: A Quick and Dirty App UI" in the repo.