How to use view and data framework in swift clean architecture

44 views Asked by At

I'm developing an app with Swift and SwifUI where GoogleCast framework is needed only for one flavor.

Imagine the view where I instantiate the GoogleCastButton:

import SwiftUI
import GoogleCast

struct NavBarView: View {
    @ObservedObject private var viewModel: NavBarViewModel
    
    init(viewModel: NavBarViewModel) {
        self.viewModel = viewModel
    }
    
    var body: some View {
        HStack {
            Text("Home")

//other view stuff...

            if viewmodel.showCastButton {
                GCKUICastButton()
            }
        }
    }
}

With the following approach, I have to use conditional compilation (#if flavourA) in the view to reuse the rest of the view and is something I don't wanna do because the app can become very complicated

I need to find a way in which I can inject a view interface or something like that in my composition root depending on the flavor but I'm not sure if this is the correct approach using MVVM + clean architecture and if so I'm not sure on how to do it properly

On the other hand, if I follow the dependency injection approach that I mentioned I will need to implement a FakeGoogleCastButton: GoogleCastButton which returns an empty view no?

If yes I would also need to create a FakeGoogleCastService: CastService to use in the data layer?

I have the feeling that I am not understanding how to correctly apply the principles of clean architecture in this case.

Maybe there is another type of interface adapter for this situation?

I created a CastRepository and a CastService interfaces to use the Google Cast data in my use cases but I don't know how I should approach the UI

1

There are 1 answers

0
malhal On

In SwiftUI the View struct already is the view model, thus it already is MVVM and already is clean. SwiftUI automatically manages the UI layer (i.e. UIKit UIView objects) from these View struct lightweight descriptions and keeps them up to date. If you try to code view model objects on top you'll just run into major issues so it's best to just learn the View struct, and how body is called when ever any @State var, @Binding var or let changes. You'll also need to use computed vars to transform data as you pass it in to a child View. If you want to group related vars with testable logic you can make a @State custom struct but have to learn about mutating func.

For your service, usually those are EnvironmentKey structs, that way they can be easily replaced with a mock for Previews. Usually they have an async func you can call from .task that returns results you can store in @State. See Apple's @Environment(\.authorizationController) for an example.