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

如何可靠地检测iOS 9上是否连接了外部键盘?,ios,objective-c,keyboard,ios9,Ios,Objective C,Keyboard,Ios9,在iOS 9之前,确定是否连接了外部键盘的最可靠方法是侦听UIKeyboardWillShowNotification,并使文本字段成为第一响应者,如中所述。通知将在使用虚拟键盘时发出,但在使用外部键盘时不会发出 然而,iOS 9现在改变了这种行为UIKeyboardWillShowNotification在连接外部键盘时也会触发,因为现在显示了新的键盘工具栏 仍然可以检测键盘高度并判断显示的是较小的工具栏还是较大的虚拟键盘。然而,这种方法是不可靠的,因为键盘高度在不同的测试版之间发生了变化,不

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

然而,iOS 9现在改变了这种行为
UIKeyboardWillShowNotification
在连接外部键盘时也会触发,因为现在显示了新的键盘工具栏

仍然可以检测键盘高度并判断显示的是较小的工具栏还是较大的虚拟键盘。然而,这种方法是不可靠的,因为键盘高度在不同的测试版之间发生了变化,不能指望随着时间的推移保持不变


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

您可以尝试检查广告服务使用的外围设备

您应该实现委托:

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

}
-(void)centralManager:(CBCentralManager*_Nonnull)central
DidDiscoveryPeripheral:(CBPeripheral*_Nonnull)peripheral
advertisementData:(NSDictionary*_Nonnull)advertisementData
RSSI:(NSNumber*\u非空)RSSI{
}

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

[[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];
let isKeyboardConnected = GCKeyboard.coalesced != nil
或者仅检索已连接设备的列表:

EAAccessoryManager* accessoryManager = [EAAccessoryManager sharedAccessoryManager];

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

回到原来的问题,我找到了一个有效的解决方案

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

目标-C

- (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;
    }
}
Swift

@objc func keyboardWillShow(_ notification: NSNotification) {
    guard let userInfo = notification.userInfo else {return}
    let keyboardScreenEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let keyboard = self.view.convert(keyboardScreenEndFrame, from: self.view.window)
    let height = self.view.frame.size.height
    if (keyboard.origin.y + keyboard.size.height) > height {
        self.hasKeyboard = true
    }
}

我使用了莎拉·埃兰答案的变体。在某些观点上,我对她的方法有意见。我一直没有弄清楚是什么引起了这个问题。但这里有另一种方法来确定它是否是您拥有的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;
}

此代码支持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;
}
#定义Gthreshold for HardwareKeyboard Toolbar 160.f//它是非视网膜iPhone在横向模式下软件键盘的最小高度
-(bool)isHardwareKeyboardUsed:(NSNotification*)键盘通知{
NSDictionary*info=[keyboardNotification userInfo];
CGRect键盘端框;
[[info-valueForKey:UIKeyboardFrameEndUserInfoKey]getValue:&keyboardEndFrame];
浮动高度=[[UIScreen mainScreen]边界].size.height-keyboardEndFrame.origin.y;
返回高度<硬件主板工具栏的阈值;
}
注意,硬件键盘可能存在但未使用。

专用API解决方案:(必须获取专用头文件-使用RuntimeViewer)

适用于企业应用程序,无应用商店限制

#import "UIKit/UIKeyboardImpl.h"

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

如果使工具栏不相关,则键盘不会显示。要做到这一点,请将其左组和右组清空(至少在iOS 12.4上):

…如果有帮助,这里有一种快速观察的方法:

// Watch for a soft keyboard to show up
let observer = NotificationCenter.default.addObserver(forName: UIWindow.keyboardWillShowNotification, object: nil, queue: nil) { notification in
    print("no external keyboard")
}

// Stop observing shortly after, since the keyboard should have shown by now
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    NotificationCenter.default.removeObserver(observer)
}
  • 这里没有一个答案对我有用。我有iPadAir和iOS 13.x
  • 我想,通过检查键盘的高度,我就能做到这一点。就这样!请注意,当连接外部键盘时,屏幕键盘的高度约为50-60px。请参见此处的工作演示:

    因此,在您的事件中,
    键盘将显示
    ,只需获取键盘高度,看看它是否在50-60左右,如果是,那么我们可以假设连接了一个外部键盘

    @objc func keyboardWillShow(_ notification: NSNotification) {
            guard let userInfo = notification.userInfo else {return}
            let keyboardScreenEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
            let keyboard = self.view.convert(keyboardScreenEndFrame, from: self.view.window)
    
            // If with keyboard, the onscreen keyboard height is 55.
            // otherwise, the onscreen keyboard has >= 408px in height.
            // The 66 digit came from a Stackoverflow comment that the keyboard height is sometimes around that number.
            if keyboard.size.height <= 66 {
                hasExternalKeyboard = true
            } else {
                hasExternalKeyboard = false
            }
        }
    
    @objc func键盘将显示(uu通知:NSNotification){
    guard let userInfo=notification.userInfo else{return}
    让keyboardScreenEndFrame=(userInfo[UIResponder.keyboardFrameEndUserInfoKey]为!NSValue).cRectValue
    让keyboard=self.view.convert(keyboardScreenEndFrame,from:self.view.window)
    //如果使用键盘,屏幕键盘高度为55。
    //否则,屏幕键盘的高度大于等于408px。
    //66位数字来自Stackoverflow的评论,即键盘高度有时在该数字附近。
    
    如果keyboard.size.heightiOS 14 SDK最终为此带来了公共API:
    GCKeyboard
    。要检查外部键盘是否已连接:

    [[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];
    
    let isKeyboardConnected = GCKeyboard.coalesced != nil
    
    注:

    • 导入游戏控制器
    • 如果可用(iOS 14.0,*),您可能需要将其包含在

    只是一个问题。为什么您需要知道是否连接了外部键盘?@agy以便启用仅在用户使用外部键盘时才应启用的功能。这个如何?它与iOS9一起工作,但我不知道您是否可以检测到外部键盘已连接。我想知道是否连接了键盘附加,以便我可以显示键盘快捷键(不是您使用命令键获得的快捷键)-我想允许键入1、2、3。不会有文本字段。我想检测是否连接了任何类型的外部键盘。我不想寻找特定的附件。@SarahElan这可能会引导您找到解决方案。您能对此进行扩展吗?这需要更多信息才能成为有用的答案。然后,您如何判断连接的附件是一个键盘?我用条形码扫描仪试过,但它没有显示在这个列表中。这是我最初使用的路径,它确实很好地完成了工作