Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the right architecture to design classes for SwiftUI app

I am bit new to app development in SwiftUI. In last 2-3 months I have developed few small iOS app just to learn concepts. Otherwise I am experienced developer in C#, Java etc.

One thing I am little unsure about SwiftUI is the right set of architecture around developing classes for the project. I mean like there could be couple of ways

  1. We write model classes that represent the data that our application need to hold. In purist form the model classes should only be concerned about just data, I mean the model classes should only hold the attributes that reflect the data.

Say I am writing a Inventory management app so if one of the model is Merchandise item then its attribute could be Id, name, price, barcode etc. In my opinion the model classes should not concerned about View's concern like @Published, @ObservableObject, @State, @EnvironmentObject etc etc. Model should just stick to representing domain only. Correct?

Ideally the model classes should be written as Class not Struct (if I carry over my understanding of OOPS from C++ to Java/C# where we write classes not struct)

  1. The second set of classes we need are views i.e. inherited from View. Undoubtedly these has to be Struct as SwiftUI framework works this way.

Now in between the model classes (presuming they are classes or at max we made them Struct for the sake of SwiftUI framework) and View classes, lots of communication, state change, eventing has to happen to make app worthy of doing something. I mean handling user gestures, creating & editing data which should update screens when user navigate back and forth between UIs.

I found it little hard to connect Model (if they are developed in purist form) and View. Hard in the sense that as I started writing Views and look to implement use cases which involve data editing, reflecting changes in views etc I found pure model classes insufficient. They have to be modified to reflect SwiftUI features like binding, observability, published to sync data between view and model and also between two models.

Wondering what is the right design pattern to connect and communicate between model and view? Is MVVM the right design pattern to be used in SwiftUI based project? If not then what else is right pattern?

If MVVM is right pattern then are there any quality guide or resources or sample SwiftUI projects (gitHub??) I can look at and learn?

like image 720
Ishwar Jindal Avatar asked Sep 05 '25 16:09

Ishwar Jindal


1 Answers

I think your hypothesis is wrong.

Ideally the model classes should be written as Class not Struct

Make a distinction between model with and without state.

Model without state should be value type.

Model with state should be reference type.

The second set of classes we need are views i.e. inherited from View. Undoubtedly these has to be Struct as SwiftUI framework works this way.

Value type cannot be inherited. I also think they are models rather than views.

E.g.; struct Model: View {}

They are models, that can be used to build views, hence the View conformance.

The fact that it is of value type also supports that it's not view. (cannot be inherited)

Whether your model has state or not, as long as it conforms to View, it can be used to render a view. This is the design of SwiftUI, taking a page from React, IMO. (I personally don't see React ever bothering with MVVM)

Now since you think Model should be strictly without state, you have a problem.

You need a reference type object that handles all the state and bridge it to the view.

You can follow MVVM. In that case you lose most of the SDK support that builds around struct Model: View, e.g.; @State, @StateObject, @EnvironmentObject, and associated automatic binding and safety checks. You would also add at least one reference type for each of the views, and put most of the control / business logic in it. (where else can you put it?)

So it's in effect a view controller. And you would be doing most of the Control work on a reference type object, without safe guards of immutability. That is on top of all the overheads you would introduce; and since you would pass view model around to be "reusable", you are going to have all the usual bugs caused by shared reference with implicit states.

Take my above assessment with a grain of salt, of course.

Or you can do what official guide do: struct Model: View {} with possible states in it.

The key here, as SDK requires you to put extra annotation, is that state objects are explicitly identified. E.g.; @StateObject, @ObservableObject. And you have to create reference type objects separate from your model. It essentially cuts out the middle man that is view model.

I think this is the most difficult thing for MVVM devs to get used to. You no longer need a view model to do what a view model does.

But shouldn't it be obvious? View model depends on how binding is designed. If SwiftUI has a binding design so efficient, (it does so declaratively without extra object) view model could be automatic.

SwiftUI removes UIViewController, does that mean you can't have Control?

I don't see MVC developers come out and create a Controller for every view.

Same reasoning, you can have MVVM without VM. Design pattern is a @State of mind.

To summarize:

I think the best architecture is official SDK. Learn to walk before you run.

MVVM in legacy sense is an option too. But I think you need to consider the possibility that

traditional wisdom is not up-to-date with latest SDK.

like image 76
Jim lai Avatar answered Sep 07 '25 12:09

Jim lai