Reputation: 5400
I'm trying return View
based selected menu item on function. But it throws error:
Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements.
There my code:
enum MenuItem {
case Main
case Report
}
struct Menu: View {
@State var activeItem: MenuItem = .Main
private func getActiveView() -> View {
switch activeItem {
case .Main:
return DashboardView()
case .Report:
return ReportView()
}
}
var body: some View {
...
getActiveView()
...
}
}
struct DashboardView: View {
var body: some View {
Text("Contact")
}
}
struct ReportView: View {
var body: some View {
Text("Contact")
}
}
Im new on SwiftUI
. Any ideas how to return View
?
Upvotes: 4
Views: 2758
Reputation: 2859
SwiftUI gives us a type-erased wrapper
called AnyView
that we can return.
Tested Solution:
struct Menu: View {
@State var activeItem: MenuItem = .Main
func getActiveView() -> some View {
switch activeItem {
case .Main:
return AnyView(DashboardView())
case .Report:
return AnyView(ReportView())
}
}
var body: some View {
getActiveView()
}
}
Note:
type-erased wrapper
effectively forces Swift to forget about what specific type is inside theAnyView
, allowing them to look like they are the same thing. This has a performance cost, though, so don’t use it often.
For more information you can refer to the this cool article: https://www.hackingwithswift.com/quick-start/swiftui/how-to-return-different-view-types
Upvotes: 4
Reputation: 257663
SwiftUI 2
Here is a solution tested with Xcode 12b / iOS 14
struct Menu: View {
@State var activeItem: MenuItem = .Main
// make function ViewBuilder
@ViewBuilder
private func getActiveView() -> some View {
switch activeItem {
case .Main:
DashboardView() // don't use 'return' as it disables ViewBuilder
case .Report:
ReportView()
}
}
var body: some View {
getActiveView()
}
}
Upvotes: 6