aturan23
aturan23

Reputation: 5400

SwiftUI can not return View on function

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

Answers (2)

Rahul Umap
Rahul Umap

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 the AnyView, 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

Asperi
Asperi

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

Related Questions