Search code examples
objective-cios14

Connecting multiple keyboards in iOS 14 Objective-C


iOS 14 introduced GCKeyboard. I was able to successfully connect a BlueTooth NumberPad in my app but I need to be able to connect two of them in tandem. Could anyone please point me to sample code?

In the GCController class there is a "controllers" method which returns an array of all connected controllers, but there isn't anything similar for GCKeyboard.

Here is my code:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[UIApplication sharedApplication]setIdleTimerDisabled:YES];

    // notifications for keyboard (dis)connect
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWasConnected:) name:GCKeyboardDidConnectNotification object:nil];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWasDisconnected:) name:GCKeyboardDidDisconnectNotification object:nil];
}

GCKeyboard *leftKeyboard;
GCKeyboard *rightKeyboard;

- (void)keyboardWasConnected:(NSNotification *)notification {
    
    if (!self.leftKeyboard) {
        leftKeyboard = (GCKeyboard *)notification.object;
        NSLog(@"Left Keyboard connected: %@\n", leftKeyboard.description);
        NSString *keyboardStatus = [NSString stringWithFormat:@"Left Keyboard CONNECTED:\n%@", leftKeyboard.description];
        self.statusLabel.text = keyboardStatus;
        
        self.leftKeyboard = leftKeyboard;
        [self reactToKeyboardInput];
    }
    else if (!self.rightKeyboard) {
        NSLog(@"Right Keyboard connected: %@\n", rightKeyboard.description);
        rightKeyboard = (GCKeyboard *)notification.object;
        NSString *keyboardStatus = [NSString stringWithFormat:@"Right Keyboard CONNECTED:\n%@", rightKeyboard.description];
        self.statusLabel.text = keyboardStatus;
        
        self.rightKeyboard = rightKeyboard;
        [self reactToKeyboardInput];
    }
}

- (void)keyboardWasDisconnected:(NSNotification *)notification {
    
    if (self.leftKeyboard) {
        GCKeyboard *keyboard = (GCKeyboard *)notification.object;
        NSString *status = [NSString stringWithFormat:@"Left Keyboard DISCONNECTED:\n%@", keyboard.description];
        self.statusLabel.text = status;
    
        self.leftKeyboard = nil;
    }
    else if (self.rightKeyboard) {
        GCKeyboard *keyboard = (GCKeyboard *)notification.object;
        NSString *status = [NSString stringWithFormat:@"Right Keyboard DISCONNECTED:\n%@", keyboard.description];
        self.statusLabel.text = status;
    
        self.rightKeyboard = nil;
    }
}

When a keyboard or number pad is connected I get the message:

2020-09-18 13:09:15.845943-0700 Controller[1653:351628] Left Keyboard connected: GCController 0x280bb8dd0 ('Keyboard' - 0x27c3dc28cec4d818)
 

Solution

  • "Bring keyboard and mouse gaming to iPad" WWDC video transcript states:

    In the case of keyboards, you can't differentiate multiple keyboards, and all keyboard events from multiple keyboards are instead coalesced for you. So while you might use notifications to notice when a keyboard disconnects and perhaps pause the game to prompt for different input, in general, you'll find that just using GCKeyboard-Device.coalesced to check on the key state when non-nil is the right path.

    So while you may have multiple keyboards connected, it sounds like they all get coalesced into a single GCKeyboard instance and you can't differentiate between them. That is why there's no +[GCKeyboard keyboards] method. Instead there is +[GCKeyboard coalescedKeyboard]