GCController not working properly when open a second ViewController

i have a problem with the GCController framework:

I have 2 viewcontrollers, each of them have a button to load the other viewcontroller.

First controller code:

import Cocoa
import GameController
class ViewController: NSViewController {

    @IBAction func abirVc2(_ sender: Any) {
       
        if let controller = self.storyboard?.instantiateController(withIdentifier: "ViewController2") as? ViewController2 {
            self.view.window?.contentViewController = controller
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        startWatchingForControllers()

        // Do any additional setup after loading the view.
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
    func startWatchingForControllers() {
        // Subscribe for the notes
        let ctr = NotificationCenter.default
        ctr.addObserver(forName: .GCControllerDidConnect, object: nil, queue: .main) { note in
            if let ctrl = note.object as? GCController {
                self.add(ctrl)
            }
        }
        ctr.addObserver(forName: .GCControllerDidDisconnect, object: nil, queue: .main) { note in
            if let ctrl = note.object as? GCController {
                self.remove(ctrl)
            }
        }
        // and kick off discovery
        GCController.startWirelessControllerDiscovery(completionHandler: {})
    }
    
    func stopWatchingForControllers() {
        GCController.stopWirelessControllerDiscovery()
        let ctr = NotificationCenter.default
        ctr.removeObserver(self, name: .GCControllerDidConnect, object: nil)
        ctr.removeObserver(self, name: .GCControllerDidDisconnect, object: nil)
    }
    
    func add(_ controller: GCController) {
        let name = String(describing:controller.vendorName)
        if let extendedGamepad = controller.extendedGamepad {
            print("connect extended \(name)")
            configureDPadButtons(extendedGamepad)
            //configureDiamondButtons(extendedGamepad)
            //configureShoulderButtons(extendedGamepad)
            //configureTriggers(extendedGamepad)
            return
        } else if let gamepad = controller.microGamepad {
            print("connect micro (name)")
        } else {
            print("Huh? (name)")
        }
    }
    private func configureDPadButtons(_ gamepad: GCExtendedGamepad) {
        
        gamepad.dpad.up.pressedChangedHandler = {(button, value, pressed) in
            
            if let controller = self.storyboard?.instantiateController(withIdentifier: "ViewController2") as? ViewController2 {
                    self.view.window?.contentViewController = controller
            }
        }
        
        gamepad.dpad.down.pressedChangedHandler = {(button, value, pressed) in
            print("ExtendedGamepad - Down")
        }
        
        gamepad.dpad.left.pressedChangedHandler = {(button, value, pressed) in
            print("ExtendedGamepad - Left")
        }
        
        gamepad.dpad.right.pressedChangedHandler = {(button, value, pressed) in
            print("ExtendedGamepad - Right")
         }
        
    }
    func remove(_ controller: GCController) {

    }

}

Second Controller code:

import Cocoa

class ViewController2: NSViewController {

    @IBAction func abrirHomeView(_ sender: Any) {
        if let controller = self.storyboard?.instantiateController(withIdentifier: "HomeView") as? ViewController {
            self.view.window?.contentViewController = controller
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
    }
    
}

On the first controller i press the button to load the second, and then press the second viewcontroller´s button to return to the first one. And it works everytime I press the buttons.

Then i use the GamePad´s Up arrow to load viewController 2, it loads correctly, then i use the button on second viewcontroller to return to first controller, ok it works too, but if i use the GamePad´s up button to load the second controller again, it does not do anything...

It seems that function that handles the GamePad Up arrow can´t load again the second viewController.

I used a simple project to make the test and it´s simple as this, 2 view controllers with one button each...

I don´t know what is happening...

Thanks in advance

Replies

Hi Pablormago

In addition to listening for the GCControllerDidConnectNotification in your startWatchingForControllers() method, your view controller should also enumerate over the GCController.controllers array to look for already connected controllers.

The GCControllerDidConnectNotification is only posted when a controller connects. There is a bit of subtlety in the current implementation where the first code that registers an observer for the GCControllerDidConnectNotification causes the GameController framework to lazily initialize, resulting in the GCControllerDidConnectNotification being posted for any found controllers. But the second time your application returns to "view controller 1", the GameController framework is already initialized, so further GCControllerDidConnectNotifications will only posted when a new controller connects.

  • I think this is a similar question: I'm trying to display the virtual controller on a second VC with no luck. I do not even attempt to use it until the second view controller. Yet I can get the virtual controller to display on the first VC. I do see that GCVirtualController is connected. But it doesn't even appear buried under a view. I've stripped them all away. Do you know what the issue is? Thanks.

Add a Comment

Thanks for your answer, but the problem was that the second ViewController was not in memory, using singleton class i achieved!!

  • My problem sounds the same. Can't get the virtual controller to appear on a second VC. I don't want it on the first VC (although I can easily get that to work). How was the second VC not in memory? How does a singleton solve it? I tried to put the setup on one vc and refer to it with a singleton on the second VC but same results. Thanks.

Add a Comment