Is there a way to dismiss a SwiftUI view from within a SpriteView scene?

268 views Asked by At

My scene is presented like this

struct GameView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
    func scene(size:CGSize) -> SKScene {
        let scene = GameScene()
        scene.size = size
        scene.scaleMode = .fill
        scene.physicsWorld.gravity = CGVector.zero
        return scene
    }
    
    var body: some View {
        GeometryReader { geometry in
            if #available(iOS 14.0, *) {
                SpriteView(scene: self.scene(size:geometry.size))
                    .edgesIgnoringSafeArea(.all)
            } else {
                // Fallback on earlier versions
                Text("Game Only available from iOS 14")
            }
        }
        .navigationTitle("")
        .navigationBarHidden(true)
    }
}

In other non spriteKit views I have used self.presentationMode.wrappedValue.dismiss() to navigate back to the previous page. Is there something similar I can do in this case once the end of the game has been triggered from within the scene? (All the views are within a navigation view)

1

There are 1 answers

0
James Castrejon On

Sort of. I don't think at moment you can do that but what I have done for my game (and i'm not sure if this is good coding practice or not) is using a ViewManager.

What the ViewManager does is it sets certain views as hidden or visible by containing a bool value for that view or views. The bool value changes from within the scene and it reflects on to swiftui.

Here is an example:

class ViewManager: ObervableObject {

    @Published private var exitView = false

    public static var shared = ViewManager()

    privat init() { }
}

class level: SKScene {
    /*Game Code*/
    override func update(_ currenTime: Interval) {
        if /*end level condition*/ {
            ViewManager.shared.exitView = true
        }
    }
}

struct GameView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @StateObject private var viewManager = ViewManager.shared

    /*your code here*/

    var body: some View {
        ZStack {
            /*SpriteView*/
            if viewManager.exitView {
                Button {
                    presentationMode.wrappedValue.dismiss()
                    viewManager.exitView = false
                } label: {
                    Image(systemName: "arrow.uturn.left")
                }
            }
        }
    }
}

The ViewManager is more of a workaround and it helps a lot.