You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 14下Objective-C连接多个GCKeyboard的技术求助

解决iOS 14中同时连接两个GCKeyboard设备的问题

我来帮你搞定同时连接两个蓝牙数字键盘的需求,先梳理下现有代码里的几个小问题,再给你完整的实现方案:

现有代码的核心问题

  1. 断开逻辑不准确:之前的断开处理没有判断具体是哪个键盘断开,只是按顺序置空,会导致误判(比如断开右键盘时可能错误清空左键盘引用)
  2. 缺少启动时已连接设备的检测:只能靠连接通知捕获新设备,App启动前已经连接的键盘无法被识别
  3. 变量管理不规范:直接在方法外声明的leftKeyboard/rightKeyboard应该改为类属性,避免作用域问题

完整修正后的代码实现

首先在你的类中添加属性声明(建议在.m的分类里或者.h中):

@interface YourViewController ()
@property (nonatomic, strong) GCKeyboard *leftKeyboard;
@property (nonatomic, strong) GCKeyboard *rightKeyboard;
@end

然后是核心实现:

- (void)viewDidLoad {
    [super viewDidLoad];
    [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
    
    // 注册键盘连接/断开通知
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWasConnected:) 
                                                 name:GCKeyboardDidConnectNotification 
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWasDisconnected:) 
                                                 name:GCKeyboardDidDisconnectNotification 
                                               object:nil];
    
    // 启动时检查已连接的键盘(解决冷启动时已连接设备无法识别的问题)
    [self checkPreConnectedKeyboards];
}

// 检查App启动前已连接的键盘
- (void)checkPreConnectedKeyboards {
    for (GCController *controller in [GCController controllers]) {
        if (controller.keyboard) {
            [self handleNewConnectedKeyboard:controller.keyboard];
        }
    }
}

// 统一处理键盘连接逻辑(复用初始化和通知触发的场景)
- (void)keyboardWasConnected:(NSNotification *)notification {
    GCKeyboard *keyboard = (GCKeyboard *)notification.object;
    [self handleNewConnectedKeyboard:keyboard];
}

- (void)handleNewConnectedKeyboard:(GCKeyboard *)keyboard {
    if (!self.leftKeyboard) {
        self.leftKeyboard = keyboard;
        NSLog(@"Left Keyboard connected: %@", keyboard.description);
        [self updateStatusLabel:[NSString stringWithFormat:@"Left Keyboard CONNECTED:\n%@", keyboard.description]];
    } else if (!self.rightKeyboard) {
        self.rightKeyboard = keyboard;
        NSLog(@"Right Keyboard connected: %@", keyboard.description);
        [self updateStatusLabel:[NSString stringWithFormat:@"Right Keyboard CONNECTED:\n%@", keyboard.description]];
    } else {
        // 超过两个设备时的提示
        NSLog(@"Third keyboard ignored: %@", keyboard.description);
        [self updateStatusLabel:@"Only two keyboards are supported!"];
    }
    // 为新连接的键盘设置输入监听
    [self setupKeyboardInputHandler:keyboard];
}

// 修正后的键盘断开逻辑(准确判断断开的设备)
- (void)keyboardWasDisconnected:(NSNotification *)notification {
    GCKeyboard *disconnectedKeyboard = (GCKeyboard *)notification.object;
    
    if (self.leftKeyboard == disconnectedKeyboard) {
        NSLog(@"Left Keyboard disconnected: %@", disconnectedKeyboard.description);
        [self updateStatusLabel:[NSString stringWithFormat:@"Left Keyboard DISCONNECTED:\n%@", disconnectedKeyboard.description]];
        self.leftKeyboard = nil;
    } else if (self.rightKeyboard == disconnectedKeyboard) {
        NSLog(@"Right Keyboard disconnected: %@", disconnectedKeyboard.description);
        [self updateStatusLabel:[NSString stringWithFormat:@"Right Keyboard DISCONNECTED:\n%@", disconnectedKeyboard.description]];
        self.rightKeyboard = nil;
    }
}

// 为键盘设置输入事件处理(区分左右键盘)
- (void)setupKeyboardInputHandler:(GCKeyboard *)keyboard {
    keyboard.keyboardInput.keyChangedHandler = ^(GCKeyboardInput *input, GCKey key, BOOL pressed) {
        if (!pressed) return; // 只处理按下事件,忽略抬起
        
        NSString *keyText = [self convertGCKeyToString:key];
        if (keyboard == self.leftKeyboard) {
            NSLog(@"Left Keyboard pressed: %@", keyText);
            // 这里添加左键盘的输入处理逻辑
        } else if (keyboard == self.rightKeyboard) {
            NSLog(@"Right Keyboard pressed: %@", keyText);
            // 这里添加右键盘的输入处理逻辑
        }
    };
}

// 辅助方法:将GCKey转换为可读字符串
- (NSString *)convertGCKeyToString:(GCKey)key {
    switch (key) {
        case GCKey0: return @"0";
        case GCKey1: return @"1";
        case GCKey2: return @"2";
        case GCKey3: return @"3";
        case GCKey4: return @"4";
        case GCKey5: return @"5";
        case GCKey6: return @"6";
        case GCKey7: return @"7";
        case GCKey8: return @"8";
        case GCKey9: return @"9";
        // 可根据需求添加更多按键映射
        default: return [NSString stringWithFormat:@"Unknown Key: %lu", (unsigned long)key];
    }
}

// 安全更新UI(确保在主线程执行)
- (void)updateStatusLabel:(NSString *)text {
    dispatch_async(dispatch_get_main_queue(), ^{
        self.statusLabel.text = text;
    });
}

// 记得在销毁时移除通知观察者
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

关键优化点说明

  1. 启动时检测已连接设备:利用GCController的controllers方法遍历所有已连接的控制器,取出其中的keyboard属性,解决冷启动时已连接键盘无法被识别的问题
  2. 准确判断断开设备:通过对象引用直接比较,确保断开操作只影响对应的键盘实例
  3. 复用连接逻辑:把连接处理抽成独立方法,避免初始化和通知触发的场景重复写代码
  4. 区分设备输入:在按键回调中通过比较键盘对象,明确区分左右键盘的输入事件

内容的提问来源于stack exchange,提问作者Val Nenov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 13:02:37