Comment détecter de manière fiable si un clavier externe est connecté sur iOS 9?

avant iOS 9, la méthode la plus fiable pour déterminer si un clavier externe est connecté était d'écouter UIKeyboardWillShowNotification et de faire un champ de texte le premier répondant, comme discuté dans cette question . La notification se déclencherait lorsqu'on utilise le clavier virtuel, mais pas lorsqu'on utilise un clavier externe.

cependant ce comportement a changé avec iOS 9. UIKeyboardWillShowNotification s'allume aussi lorsqu'un clavier externe est connecté, puisque la nouvelle barre d'outils du clavier est maintenant affichée.

il est encore possible de détecter la hauteur du clavier et de juger si c'est la barre d'outils plus petite ou le clavier virtuel plus grand qui est affiché. Cependant, cette méthode n'est pas fiable puisque la hauteur du clavier a changé entre les différents beta et ne peut pas être comptée pour rester la même au fil du temps.

Existe-t-il une méthode plus fiable qui puisse être utilisée avec iOS 9?

30
demandé sur Community 2015-08-13 18:00:24

6 réponses

après être retourné à la question originale, j'ai trouvé une solution qui fonctionne.

il semble que lorsque le clavier virtuel habituel est affiché, le cadre du clavier se trouve dans les dimensions de l'écran. Toutefois, lorsqu'un clavier physique est connecté et que la barre d'outils du clavier est affichée, le cadre du clavier est situé hors écran. Nous pouvons vérifier si le cadre du clavier est hors écran pour déterminer si la barre d'outils du clavier est affichée.

- (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;
    }
}
46
répondu Sarah Elan 2015-09-01 18:19:57

ce code prend en charge iOS 8 et iOS 9, inputAccessoryView, a une constante à double protection pour être prêt à de nouvelles modifications dans les futures versions de iOS et de prendre en charge de nouveaux appareils:

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

Note, un clavier matériel peut être présent mais non utilisé.

4
répondu Dmitry 2016-02-13 21:35:47

j'utilise une variation sur la réponse de Sarah Elan. J'ai eu des problèmes avec son approche dans certains points de vue. Je n'ai jamais vraiment compris ce qui a causé le problème. Mais voici une autre façon de déterminer si c'est un clavier externe iOS9 'undo' bar que vous avez, plutôt que le clavier complet.

il n'est probablement pas très vers l'avant compatible car s'ils changent la taille de la barre d'Annulation, ce freins. Mais, il fait le travail. Je me félicite des critiques formulées à ce sujet. doit y avoir une meilleure façon...

//... 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;
}
2
répondu Mike 2015-09-21 05:35:25

solution API privée: (doivent saisir le fichier d'en - tête privé-utiliser RuntimeViewer).

fonctionne bien pour les applications d'entreprise, où vous n'avez pas de restrictions AppStore.

#import "UIKit/UIKeyboardImpl.h"

+ (BOOL)isHardwareKeyboardMode
{
   UIKeyboardImpl *kbi = [UIKeyboardImpl sharedInstance];
   BOOL externalKeyboard = kbi.inHardwareKeyboardMode;
   NSLog(@"Using external keyboard? %@", externalKeyboard?@"YES":@"NO");
   return externalKeyboard;
}
1
répondu Simon Tillson 2017-08-03 09:09:47

vous pouvez vous abonner à la notification lorsque le périphérique externe est connecté:

[[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];

ou juste récupérer la liste des dispositifs attachés:

EAAccessoryManager* accessoryManager = [EAAccessoryManager sharedAccessoryManager];

if (accessoryManager)
{
    NSArray* connectedAccessories = [accessoryManager connectedAccessories];
    NSLog(@"ConnectedAccessories = %@", connectedAccessories);
}
0
répondu Javier Calatrava Llavería 2016-05-26 05:34:32

vous pouvez essayer de vérifier les périphériques qui sont des services de publicité en utilisant noyau Bluetooth

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

et vous devez mettre en œuvre le délégué:

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

}
-1
répondu agy 2015-08-25 21:13:30