Reputation: 11
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
Upvotes: 0
Views: 285
Reputation: 223
ref: clean-architecture-swiftui
Upvotes: -1
Reputation: 30746
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.
Upvotes: 1