In out project, we are creating a modular architecture where each module conform to certain protocol requirements for displaying the UI.
For example:
public protocol ModuleProviding: Sendable {
associatedtype Content: View
/// Creates and returns the main entry point view for this module
/// - Parameter completion: Optional closure to be called when the flow completes
/// - Returns: The main view for this module
@MainActor
func createView(_ completion: (() -> Void)?) -> Content
}
This protocol can be implemented by all different modules in the app, and I use a ViewProvider
structure to build the UI from the module provided:
public struct ViewProvider: Equatable {
let id = UUID()
let provider: any ModuleProviding
let completion: () -> Void
public init(provider: any ModuleProviding, completion: @escaping () -> Void) {
self.provider = provider
self.completion = completion
}
@MainActor
public func layoutUI() -> some View {
provider.createView(completion)
}
This code throws an error:
Type 'any View' cannot conform to 'View'
To solve this error, there are two ways, one is to wrap it in AnyView
, which I don't want to do.
The other option is to type check the provider
with its concrete type:
@ViewBuilder @MainActor
private func buildViewForProvider(_ provider: any ModuleProviding, completion: (() -> Void)?) -> some View {
switch provider {
case let p as LoginProvider:
p.createView(completion)
case let p as PostAuthViewProvider:
p.createView(completion)
case let p as OnboardingProvider:
p.createView(completion)
case let p as RewardsProvider:
p.createView(completion)
case let p as SplashScreenProvider:
p.createView(completion)
default:
EmptyView()
}
}
This approach worked, but it defeats the purpose of using protocols and it is not scalable anymore.
Are there any other approaches I can look at ? Or is this limitation in SwiftUI ?