So i have a view that takes viewModel containing array of elements providing views to build body in ForEach
And it looks like this:
struct MainTabView: View {
@ObservedObject var viewModel: TabViewModel
var body: some View {
TabView {
ForEach(viewModel.tabs, id: .title) { tab in
tab.view
.tabItem {
Image(systemName: tab.imageName)
Text(tab.title)
}
}
}
}
}
struct HomeView: View {
var body: some View {
VStack {
Text("Home")
.font(.largeTitle)
.padding()
Spacer()
}
}
}
class TabViewModel: ObservableObject {
@Published var tabs: [TabItem] = [
TabItem(title: "Home", imageName: "house.fill", view: AnyView(HomeView()))
]
}
struct TabItem {
let title: String
let imageName: String
let view: AnyView
}
So I am trying to figure out a proper way to decouple our views from concrete types and also not use AnyView. But other then code above I could not come up with compilable code or find any helpful solution online.
Please can anyone explain to me the way to go abut concrete types, and dependency injection in SwiftUI in context of above code?
I tried to use protocols like:
protocol TabViewProviding {
var title: String { get }
var imageName: String { get }
var tabView: any View { get }
}
protocol TabViewModelProviding: ObservableObject {
var tabs: [TabViewProviding] { get }
}
and replace concrete types with generics but best i got was errors like
Static method 'buildExpression' requires that 'Content' conform to 'AccessibilityRotorContent'
or just coupling concrete types in different places.
1