Need advice on modeling for SwiftUI (PATs and struct vs class, oh my!)

I've been working on my first real SwiftUI app (in macOS), and I've come to a point where I need to really implement my model. I suppose this is another form of “should this be a struct or a class?” but I don't yet have the intuition to know with any certainty that there's no way it could be a struct (I try to make things structs where possible). But I'm running into a protocols-with-associated-types issue, in that I wanted to make my root data object an array of protocols, but they have to conform to Identifiable, and that's not allowed (protocols with associated types can only be used as constraints).

Document Data Model

The app document is a kind of project, analogous to Xcode, wherein there's a left-hand pane, a list of entries for files, and a right-hand detail pane (source view).

In my case they're called Layers, and the data they represent is rendered visually on the right (it's a simplified GIS program). A layer can be as simple as an image file dropped onto the project window from the Finder, or it can be generated or derived from another layer.

In the first case, the model stores, say, the url to the file.

In the second case, the model stores a reference to the source layer, and some parameters describing how the derived data was generated. It probably also references a cache of that generated data.

Questions

Is this already clearly not a struct? Am I missing a Swiftism that would let me build more of these models with structs? Is heavy use of type erasure (something I've only studied briefly) to be expected in a "proper" Swift app like this?

Or do I just use classes and call it a day. I understand those fairly well :wink:

I just recently dove into document based apps in SwiftUI and needed to figure out a couple things.

Your document type will be a package (conforms to com.apple.package). If every possible mutation should be undoable then you should be fine with a struct as a document model which would conform to FileDocument and it has to obey value semantics, which is very important for that matter. If you need more precise control and also un-undoable mutation of the model then you will need ReferenceFileDocument which will force your model to be an object.

Here is a gist where I also added a convenience type one could build to reduce the footprint of repeating document related operations.

For a bit more details refer to my answer here. The example there is also a bit more simplified: https://stackoverflow.com/a/67200964