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

时间:2015-08-13 15:00:25

标签: ios objective-c keyboard ios9

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

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

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

是否有更可靠的方法可以与iOS 9一起使用?

9 个答案:

答案 0 :(得分:48)

回到最初的问题后,我找到了一个有效的解决方案。

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

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

答案 1 :(得分:4)

此代码支持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;
}

注意,硬件键盘可能存在但未使用。

答案 2 :(得分:2)

我正在使用Sarah Elan的答案。我在某些观点中遇到了问题。我从来没有完全了解导致问题的根源。但这是确定它是否是ios9外置键盘的另一种方法&#39;撤消&#39;你有的吧,而不是全尺寸的键盘。

它可能不是非常向前兼容,因为如果它们改变了撤销条的大小,这就会制动。但是,它完成了工作。我欢迎批评,因为必须有更好的方式......

//... 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;
}

答案 3 :(得分:2)

私有API解决方案:(必须获取私有头文件 - 使用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;
}

答案 4 :(得分:2)

iOS 14 SDK终于为此带来了公共API:GCKeyboard。要检查是否连接了外部键盘:

let isKeyboardConnected = GCKeyboard.coalescedKeyboard != nil

注意:

  • import GameController
  • 您可能需要将其包含在if #available(iOS 14.0, *)

答案 5 :(得分:1)

如果使工具栏不相关,则键盘不会显示。为此,请清空其左右组(至少在iOS 12.4上):

textField.inputAssistantItem.leadingBarButtonGroups = []
textField.inputAssistantItem.trailingBarButtonGroups = []

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

// 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)
}

答案 6 :(得分:0)

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

[[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);
}

答案 7 :(得分:0)

  1. 这里没有答案对我有用。我有带iOS 13.x的iPad Air。

我认为可以通过检查键盘的高度来做到这一点。而已!请注意,当连接了外部键盘时,屏幕键盘的高度约为50-60px。在此处查看工作示例:https://youtu.be/GKi-g0HOQUc

因此,在您的事件keyboardWillShow中,只需获取键盘高度,看看它是否在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
        }
    }

答案 8 :(得分:-1)

您可以尝试使用Core Bluetooth

检查广告服务的外围设备
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{

}