How to open specific scene using local notifications and SpriteKit?

111 Views Asked by At

Let's say I have GameViewController, SceneMenu, Scene1 and Scene2.

My default scene is SceneMenu and from there I can navigate between all 3 scenes.

I also implemented local notifications which contains additional information in userInfo. And I am able to successfully retrieve this information when user tap on the notification. However, I am unable to figure out how to open specific scene based on the information provided in userInfo. For example, I'd like to open dynamically Scene1 or Scene2 when user tap on the notification and when user goes to app directly, I'd like to show him SceneMenu.

Thanks for help in advance.

Here is the sample code from GameViewController.swift which opens SceneMenu and sendNotification function.

import SpriteKit
import UserNotifications

class GameViewController: UIViewController {

let center = UNUserNotificationCenter.current()

override func viewDidLoad() {
    
    let scene = SceneMenu(size: view.frame.size)
    scene.scaleMode = .aspectFit
    scene.backgroundColor = .white
    
    let view = view as! SKView
    view.presentScene(scene)
    
    view.showsFPS = true
    view.showsNodeCount = true
    
    requestNotificationAuthorization()
    
}

func requestNotificationAuthorization() {
    
    let authOptions = UNAuthorizationOptions(arrayLiteral: .alert, .badge, .sound)
    
    center.requestAuthorization(options: authOptions) { (success, error) in
        if let error = error {
            print("error: \(error)")
        }
    }
    
}

func sendNotification(scene: String) {
    
    let content = UNMutableNotificationContent()
    
    content.title = "title"
    content.body = "body"
    content.badge = NSNumber(value: 3)
    content.userInfo = ["scene": scene]
    
    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
    let request = UNNotificationRequest(identifier: "testNotification", content: content, trigger: trigger)
    
    center.add(request)
    
}

}

AppDelegate.swift sample code:

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    
    let userInfo = response.notification.request.content.userInfo
    
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "testNotification"), object: nil, userInfo: userInfo)
    completionHandler()
    
}

SceneMenu.swift sample code:

    override func didMove(to view: SKView) {
    
    NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "testNotification"), object: nil, queue: nil) { [weak self] (notification) in
        guard let strongSelf = self else {
            return
        }
        guard let name = notification.userInfo?["scene"] as? String else {
            return
        }
        strongSelf.testFunction(scene: scene)
    }
    
}

and testFunction which I planned to use to go to specific scene (however it doesn't work and I am also not sure if this is the best way of doing it):

func testFunction(scene: String) {
    
    switch scene {

    case "scene1":
    print("scene1")
    let scene = Scene1(size: size)
    scene.backgroundColor = .white
    self.view?.presentScene(scene)
    break

    case "scene2":
    print("scene2")
    let scene = Scene2(size: size)
    scene.backgroundColor = .white
    self.view?.presentScene(scene)
    break

    default:
    print("nothing")
    break

    
}
0

There are 0 best solutions below