Search code examples
swiftuisegueswiftui-navigationlink

Change view without Navigation link SwiftUI


I everyone! I spent hours looking for something that I guess very simple but I can not managed to find the best way... I have my body view :

var body: some View {
        
        VStack {
            // The CircularMenu
            CircularMenu(menuItems: homeMenuItems, menuRadius: 55, menuButtonSize: 55, menuButtonColor: .black, buttonClickCompletion: buttonClickHandler(_:))
                .buttonStyle(PlainButtonStyle())

        }
    }

Which contains a circular menu. Each click on a menu item calls :

func buttonClickHandler(_ index: Int) {
        /// Your actions here
        
        switch index {
        //Thermometer
        case 0:
            print("0")
        //Light
        case 1:
            print("1")
        //Video
        case 2:
            print("2")
        //Alarm
        case 3:
            print("3")
        //Car
        case 4:
            self.destinationViewType = .car
            self.nextView(destination: .car)
            
        default:
            print("not found")
        }
    }

I want to perform a simple view transition to another view called Car. nextView function looks like this :

func nextView(destination: DestinationViewType) {
        
        switch destination {
            case .car: Car()
        }
    }

I thought that was simple like this but I get : Result of 'Car' initializer is unused on the case line. So someone knows how to achieve that ? Thanks a lot in advance!


Solution

  • Here's one way to do it:

    Create a struct called IdentifiableView which contains an AnyView and an id:

    struct IdentifiableView: Identifiable {
        let view: AnyView
        let id = UUID()
    }
    

    Create a @State var to hold the nextView. Use .fullScreenCover(item:) to display the nextView

    @State private var nextView: IdentifiableView? = nil
    
    var body: some View {
            
            VStack {
                // The CircularMenu
                CircularMenu(menuItems: homeMenuItems, menuRadius: 55, menuButtonSize: 55, menuButtonColor: .black, buttonClickCompletion: buttonClickHandler(_:))
                    .buttonStyle(PlainButtonStyle())
    
            }.fullScreenCover(item: self.$nextView, onDismiss: { nextView = nil}) { view in
                view.view
            }
    }
    

    Then, assign self.nextView the IdentifiableView:

    case .car: self.nextView = IdentifiableView(view: AnyView(Car()))
    

    When it's time to return to the MenuView use self.presentationMode.wrappedValue.dismiss() to dismiss the view. Here is an example of a minimal Car view:

    struct Car: View {
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
        var body: some View {
            Text("Car View").onTapGesture {
                self.presentationMode.wrappedValue.dismiss()
            }
        }
    }