1
votes

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!

2
Does this answer your question stackoverflow.com/a/63782921/12299030?Asperi
Thanks but this method use navigationlink. I do not want to use this.Silvering
At which line of code you found NavigationLink? ;)Asperi
@Silvering Does my answer for Go to a new view using SwiftUI help?George

2 Answers

2
votes

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()
        }
    }
}
1
votes

If you want to completely replace the body content with the new view, you need some condition about that. Let's say you have a Container with a body and if there is a Car view created we will display it:

struct Container: View {

    @State var car: Car?      // Storage for optional Car view

    var body: some View {
        if let car = car {    // if the car view exists
            car               // returning the car view
        } else {              // otherwise returning the circular menu
            VStack {
                CircularMenu(menuItems: homeMenuItems, menuRadius: 55, menuButtonSize: 55, menuButtonColor: .black, buttonClickCompletion: buttonClickHandler(_:))
                .buttonStyle(PlainButtonStyle())
            }
        }
    }
...

And then we only need to assign the newly created instance of the car view on click:

...
    func buttonClickHandler(_ index: Int) {
        switch index {
        ....
        //Car
        case 4:
        car = Car()         // assigning the newly created instance
        ...
        }
    }
}

I see that you have mentioning of destinationViewTyp and some other cases. So your code will be slightly more complex than this, but the idea keeps the same. We store either a view or some information that helps us create a view when necessary and then returning either a picker or a view depending on condition.