2

How can I present in swiftUI a view in a switch case?

import Foundation

enum SideMenuViewModel: Int, CaseIterable, Decodable {
    case Home
    case Users
    case TODOs
    case AboutUs
    
    var title: String {
        switch self {
        case .Home: return "Home"
        case .Users: return "Users"
        case .TODOs: return "TODOs"
        case .AboutUs: return "AboutUs"
        }
    
    }
    var imageName: String {
        switch self {
        case .Home: return "bookmark.circle"
        case .Users: return "person"
        case .TODOs: return "list.bullet"
        case .AboutUs: return "info.circle"
        }
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
georgekak
  • 73
  • 11
  • https://stackoverflow.com/questions/72496023/adding-animation-to-tabviews-in-swiftui-when-switching-between-tabs/72816878#72816878 – lorem ipsum Jul 25 '22 at 12:18

3 Answers3

4

You need view builder property, like

@ViewBuilder var view: some View {
    switch self {
    case .Home:
       HomeView()
    case .Users:
       UsersView()
    case .TODOs:
       TODOView()
    case .AboutUs:
       AboutUsView()
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Finally I solved with a combination of your and Dávid solution. In his solution don't need to use return. – georgekak Aug 03 '22 at 14:29
3

Instead of trying to return a View from an enum, inject the enum into your View and switch over the enum inside the view, then return the appropriate View from there.

A ViewModel should be independent from its view type, only the view should know about the VM, not the other way around.

struct SideMenuView: View {
  private let viewModel: SideMenuViewModel

  init(viewModel: SideMenuViewModel) {
    self.viewModel = viewModel
  }

  var body: some View {
    switch viewModel {
    case .AboutUs:
      AboutUsView(...)
    case .Home:
      HomeView(...)
      ...
    }
  }
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • 1
    Thank you very much. Your way of thinking help me the most. Its right your answer and I use it without return in cases. – georgekak Aug 03 '22 at 14:30
0

I would suggest to craft an enum with associated values as follows:

enum ViewState {
    case .home(HomeViewState)
    case .users(UsersViewState)
    case .todos(TodosViewState)
    case .aboutUs(AboutUsViewState)
}

So, each case has its own distinct "state" (aka model) for the respective view.

struct HomeViewState {...}
struct UsersViewState {...}
struct TodosViewState {...}
struct AboutUsViewState {...}

In a parent view, obtain the enum value, then simply select the given state using a switch statement. Extract the view specific state and compose the view in the body:

struct ContentView: View {
    let viewState: ViewState

    var body: some View {
        switch viewState {
        case .home(let state):
            HomeView(state: state)
        case .users(let state):
            UsersView(state: state)
        case .todos(let state):
            TodosView(state: state)
        case .aboutUs(let state):
            AboutUsView(state: state)
        }
    }
}

Example for the HomeView:

struct HomeView: View {
    let state: HomeViewState

    var body: some View {
        ...
    }
}

Your Model:

final class SideMenuViewModel: ObservableObject {
    @Published var viewState: ViewState = ...
    ... 
}

A root view in the scene my now subscribe to the SideMenuViewModel and pass the viewState to the ContentView.

CouchDeveloper
  • 18,174
  • 3
  • 45
  • 67