如何可靠地检测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{ }