问题
I'm trying to embrace Swift's value types more in my application design, but I'm having some beginner difficulties. I know those generally don't go over well in the StackOverflow format for being opinion-based, but I think there are best-practices here that are probably not particularly subjective.
I understand all the theoretical benefits of structs, about avoiding shared mutable state, the copying behaviour that makes it easy to implement "undo", etc., but I have a hard time using it in practice for the model layer of my app (where I think structs would be most benefitial). I don't even know if this is a worthwhile pursuit, so bear with me.
Suppose I have a collection view, whose entries model pictures and their meta data. When a picture is selected, it would bring up a detail view that lets you view and edit the details of the picture and its associated meta data (filename, gps location, description, tags, ect.).
I'm struggling with how to design the interaction between my detail view controller, and my model layer which stores the repository of all of my images.
Here are some ideas I have about how I could design the interaction between the view and model layers.
The view controller could alias the model owned by the model layer. That is, the model layer will hold a collection of models objects. When one is selected, the VC will ask the model layer for one of the objects, which will be returned by reference. When the user changes details of the image, the VC's aliasing reference will be used to access the "active" model object, and update it directly.
This sounds like the easiest approach, and is probably what I would do in other langauges (like Java), but it forces me to use a
class
to model my object, where otherwise astruct
seems more appropriate. In this context, it appears (to me) that there's no need for identity. If two picture objects have the same fields, they're indistinguishable.If I tried to keep my models as structs, my view controller could use a copy-modify-write pattern.
- When an image is selected for editing, its model is copied into the VC.
- The VC acts on its local copy, mutating it in-place
- Eventually when the change needs to be persisted (such as when switching to a new image to edit, quiting the application, etc.) the VC overwrites the model layer's value with its local copy.
This gets rids of any potential threading issues that might come with the shared mutable state in approach 1, but it comes with the downside of having the model become desyncronized from the VC, which could cause all kinds of consistency issues.
The next 3 approaches consider ideas that use a reactive framework like Combine or Rx. I could use this pattern to subscribe my VC to receive updates to changes in the model layer and its
Picture
objects. However, I'm not sure how the "other way" would work; how the VC would inform the model to update. If I made the model subscribe itself to the view, then I think I would have an infinite loop, unless I added some mechanics around which changes should trigger observers and which shouldn't.
I'm not sure which is the best one, and I suspect this is one of those things that you pick up with experience (that I don't have yet :P). Any guidance would be greatly appreciated!
来源:https://stackoverflow.com/questions/58809724/how-to-apply-structs-to-modeling-the-data-a-view-controller-operates-on