How to do Add, View, Edit (with Cancel and Done)

I'm not sure how to pull off a viewer/editor with SwiftData + SwiftUI that supports Cancel

I want the user to be able to:

  1. Tap + to bring up a sheet/form to create a new Item.
    • The navigation bar shows Cancel and Create.
    • Create is only enabled when the fields are mostly valid.
    • Tap Create to do a deeper validation and add.
    • Tap Cancel to not make any changes.
  2. Tap an item to view it.
  3. Tap Edit when viewing to edit.
    • The navigation bar shows Cancel and Done.
    • Done is only enabled when the fields are mostly valid.
    • Tap Done to do a deeper validation and save changes.
    • Tap Cancel to not make any changes.

I think is a fairly common pattern. It's used by Contacts, for instance.

I've got parts of this working. Creating is easy: I just insert it only after the user taps Create and it's validated.

But Edit/Cancel/Done seems harder. If I disable autosaving the changes to the model, the changes are applied to other parts of SwiftUI immediately. And I haven't figured out how to cancel the changes. Should I be operating on a copy of the object instead? How do I copy it in a way that doesn't impact SwiftData?

I'm happy to take any tips you might have, but if you want to look at the code and suggest something that way I put my test case up here: https://github.com/tewha/ItemEditor My hope is I can get this sample working, get the changes into my app, and keep the sample up for others to discover (though I feel this would also be a great concept for sample code).

Replies

Let's say each Item has a unique id, a UUID.

The way I've implemented this is to create a "blankItem" with default values and id = "".

My Item edit screen takes an Item as a parameter, so, if I pass the blank item to the editor it will display those default values and let the user edit it.

You can then set the buttons appropriately.

I also set some lets that store the original values from the Item that was passed in, so I can disable the Done button if nothing has actually changed, and I can alert the user that they've made changes if they press Cancel.

So, if the user tapped to create a new Item you're editing the blankItem. You assign an id once you validate the entered values are valid, and save the Item. You never save any changes to the blankItem; and you never save the blankItem to your data store. You simply use the blankItem as a way of populating the create screen with default values.

If I'm editing an existing Item, then the screen is populated with the values from that Item, and I can check they've made changes or not with those lets think "original_name", "original_location" etc.).

Because when you're editing an existing Item the id is not blank you can set the buttons here appropriately, too. And when you pass validation and save you update the actual Item based on its id.

Hope this helps.

  • It’s going to take a while for me to figure out all the code for this, but that sounds like a great approach. Thank you.

Add a Comment