Skip to content

SwiftUI Editing State: Make Save and Cancel Mean Different Things

Design a document-editing flow with separate temporary changes, saved content and export state, using Make Resume as a product discovery example.

GuideProductivity

By

Updated 3 min read
SwiftUI Editing State: phone illustration with IndieTools branding

A SwiftUI editor should make it clear whether a change exists only in the open form, has been saved to the document or has reached an exported file. Treat these as separate outcomes. Otherwise, a Cancel button can appear to discard an edit while a shared binding has already changed the underlying record.

Make Resume, a document tool in the SwiftUI collection, is a useful starting point for this kind of workflow research. Its official page describes editing a resume and exporting a PDF. The design below is an implementation exercise, not a claim about the product's private source code.

Give temporary changes an explicit owner

Apple's state guidance distinguishes transient interface state from persistent storage. It also describes bindings as references to state owned elsewhere. That distinction matters when an editing screen offers both Save and Cancel.

Write the intended behaviour before choosing a property wrapper. For a form that requires explicit confirmation, create an editable working representation and define when its accepted values reach the saved model. For an autosaving editor, make that behaviour visible and decide what Undo means instead of presenting a misleading Cancel action.

Neither approach is universally correct. Consistency between the control label and the persistence boundary is the requirement.

Use a document with recognisable changes

Prepare fictional resume content containing a short name, two employment entries and a deliberately long role description. Change one field, leave another blank and reorder the entries. Keep the original document available for comparison.

Check the result after saving, cancelling, leaving the screen and reopening it. Repeat with the application interrupted while an edit is incomplete. Record which values are expected to survive each transition; do not assume the view's lifetime is the same as the document's lifetime.

The test should compare actual values, not just a success toast. A message can appear even when an older value is later restored.

Validate without erasing the user's work

If a value cannot be accepted, show the relevant problem while retaining the rest of the input. Distinguish a local formatting issue from a failed persistence operation. The person correcting a date should not need to retype an entire employment history.

Consider what happens if the saved record changes while an editing screen is open. A second device, background synchronisation or another view may be responsible. Establish whether the app rejects stale edits, merges specific fields or asks the user to choose. Keep that policy independent of the visual form layout.

Check the export boundary

A PDF export introduces another snapshot. Confirm which saved or unsaved version it represents and show an actionable error if generation fails. Use the same recognisable sample to compare text, ordering and page breaks in the exported artifact.

Keep export completion separate from opening a share sheet. Handing a file to another application is a further step with its own cancellation and destination behaviour. A successful document save should remain successful even if the user decides not to share the file.

Preserve the contract during refactoring

When splitting a large SwiftUI view into smaller components, rerun the save, cancel and interruption cases. Moving state ownership can change behaviour even when the screen looks identical.

The related SwiftUI list identity guide addresses another state problem: keeping actions attached to the correct item while a list changes. Together, these exercises give a native app review a more useful foundation than judging a single polished screenshot.

More guide articles