如何可靠地检测iOS 9上是否连接了外部键盘?

在iOS 9之前,确定外部键盘是否连接的最可靠的方法是侦听UIKeyboardWillShowNotification ,并将文本字段设置为第一个响应者,如本问题所述 。 使用虚拟键盘时会触发通知,但在使用外部键盘时不会触发。

但是现在这种行为已经在iOS 9中改变了。由于现在显示了新的键盘工具栏,因此在连接外部键盘时也会触发UIKeyboardWillShowNotification

还可以检测键盘高度,并判断是否显示较小的工具栏或较大的虚拟键盘。 然而这种方法是不可靠的,因为键盘的高度在各种testing版本之间已经改变,并且不能随着时间的推移而保持不变。

有没有更可靠的方法可以用于iOS 9?

回到原来的问题后,我find了一个解决scheme。

看起来,当常规的虚拟键盘显示时,键盘框架在屏幕的尺寸内。 但是,当连接了物理键盘并显示键盘工具栏时,键盘框架位于屏幕外。 我们可以检查键盘框是否在屏幕外,以确定键盘工具栏是否显示。

 - (void) keyboardWillShow:(NSNotification *)notification { NSDictionary* userInfo = [notification userInfo]; CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGRect keyboard = [self.view convertRect:keyboardFrame fromView:self.view.window]; CGFloat height = self.view.frame.size.height; if ((keyboard.origin.y + keyboard.size.height) > height) { self.hasKeyboard = YES; } } 

此代码支持iOS 8和iOS 9,inputAccessoryView,具有双重保护常量,可以在未来版本的iOS中进行新更改,并支持新设备:

 #define gThresholdForHardwareKeyboardToolbar 160.f // it's minimum height of the software keyboard on non-retina iPhone in landscape mode - (bool)isHardwareKeyboardUsed:(NSNotification*)keyboardNotification { NSDictionary* info = [keyboardNotification userInfo]; CGRect keyboardEndFrame; [[info valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame]; float height = [[UIScreen mainScreen] bounds].size.height - keyboardEndFrame.origin.y; return height < gThresholdForHardwareKeyboardToolbar; } 

请注意,硬件键盘可能会出现但不能使用。

我正在使用Sarah Elan的答案。 我在某些意见中遇到了问题。 我从来没有深究造成这个问题的原因。 但是,这是另一种方法来确定它是否是一个ios9外部键盘“撤消”栏,而不是全尺寸的键盘。

它可能不是非常向前兼容,因为如果他们改变撤消栏的大小,这刹车。 但是,它完成了工作。 我欢迎批评,因为必须有更好的方法。

 //... somewhere ... #define HARDWARE_KEYBOARD_SIZE_IOS9 55 // + (BOOL) isExternalKeyboard:(NSNotification*)keyboardNotification { NSDictionary* info = [keyboardNotification userInfo]; CGRect keyboardEndFrame; [[info valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame]; CGRect keyboardBeginFrame; [[info valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardBeginFrame]; CGFloat diff = keyboardEndFrame.origin.y - keyboardBeginFrame.origin.y; return fabs(diff) == HARDWARE_KEYBOARD_SIZE_IOS9; } 

当外部设备连接时,您可以订阅通知:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceConnected:) name:EAAccessoryDidConnectNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceDisconnected:) name:EAAccessoryDidDisconnectNotification object:nil]; [[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications]; 

或者只是检索附加设备的列表:

 EAAccessoryManager* accessoryManager = [EAAccessoryManager sharedAccessoryManager]; if (accessoryManager) { NSArray* connectedAccessories = [accessoryManager connectedAccessories]; NSLog(@"ConnectedAccessories = %@", connectedAccessories); } 

私有API解决scheme:(必须抓取私人头文件 – 使用RuntimeViewer)。

适用于没有AppStore限制的企业应用程序。

 #import "UIKit/UIKeyboardImpl.h" + (BOOL)isHardwareKeyboardMode { UIKeyboardImpl *kbi = [UIKeyboardImpl sharedInstance]; BOOL externalKeyboard = kbi.inHardwareKeyboardMode; NSLog(@"Using external keyboard? %@", externalKeyboard?@"YES":@"NO"); return externalKeyboard; } 

你可以尝试使用核心蓝牙来检查广告服务的外围设备

 CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; [centralManager scanForPeripheralsWithServices:nil options:nil]; 

你应该实现委托:

 - (void)centralManager:(CBCentralManager * _Nonnull)central didDiscoverPeripheral:(CBPeripheral * _Nonnull)peripheral advertisementData:(NSDictionary<NSString *, id> * _Nonnull)advertisementData RSSI:(NSNumber * _Nonnull)RSSI{ }