iOS 7 硬件键盘事件

Posted

技术标签:

【中文标题】iOS 7 硬件键盘事件【英文标题】:iOS 7 Hardware Keyboard Events 【发布时间】:2013-09-11 17:35:50 【问题描述】:

现在我们有了 ios 7,Apple 显然已经删除了从-sendEvent: 接收键盘通知的选项。对于想要编写捕获所有关键事件并将其发送到远程计算机 E.G. 的东西的人来说,这是一个巨大的痛苦。 VNC 客户端。 UIKeyCommand 不提供所需的功能。有很多错误报告提交给苹果,但他们不会听。错误报告苹果正在关闭所有报告,因为重复是 rdar://14129420。

什么是最好的解决方案?

【问题讨论】:

【参考方案1】:

我至少能够以私有 API 的方式将这些事件取回,但是 keyup 不会返回任何有用的信息,例如已释放的密钥。也许这是可以从UIEvent 中提取的东西?

需要添加的代码是UIPhysicalKeyboardEvent的如下定义。

@interface PhysicalKeyboardEvent : UIEvent //UIPhysicalButtonsEvent
    int _inputFlags;
    NSString *_modifiedInput;
    NSString *_unmodifiedInput;
    NSString *_shiftModifiedInput;
    NSString *_commandModifiedInput;
    NSString *_markedInput;
    long long _modifierFlags;
    NSString *_privateInput;

+ (id)_eventWithInput:(id)arg1 inputFlags:(int)arg2;
@property(retain, nonatomic) NSString *_privateInput; // @synthesize _privateInput;
@property(nonatomic) int _inputFlags; // @synthesize _inputFlags;
@property(nonatomic) long long _modifierFlags; // @synthesize _modifierFlags;
@property(retain, nonatomic) NSString *_markedInput; // @synthesize _markedInput;
@property(retain, nonatomic) NSString *_commandModifiedInput; // @synthesize _commandModifiedInput;
@property(retain, nonatomic) NSString *_shiftModifiedInput; // @synthesize _shiftModifiedInput;
@property(retain, nonatomic) NSString *_unmodifiedInput; // @synthesize _unmodifiedInput;
@property(retain, nonatomic) NSString *_modifiedInput; // @synthesize _modifiedInput;
@property(readonly, nonatomic) long long _gsModifierFlags;
- (void)_privatizeInput;
- (void)dealloc;
- (id)_cloneEvent;
- (_Bool)isEqual:(id)arg1;
- (_Bool)_matchesKeyCommand:(id)arg1;
//- (void)_setHIDEvent:(struct __IOHIDEvent *)arg1 keyboard:(struct __GSKeyboard *)arg2;
@property(readonly, nonatomic) long long _keyCode;
@property(readonly, nonatomic) _Bool _isKeyDown;
- (long long)type;
@end

要侦听事件,请在 UIResponder 中使用以下内容。我不确定响应者是否需要成为关键。

- (id)_keyCommandForEvent:(PhysicalKeyboardEvent *)event 
    //Some reason it gets called twice and it's not because of keyup. Keyup seems to not mention it's original key.
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [self performSelector:@selector(processEvent:) withObject:event afterDelay:0];
    return [super _keyCommandForEvent:event];

- (void)processEvent:(PhysicalKeyboardEvent *)event 
    NSLog(@"%@", [event _unmodifiedInput]);
    NSLog(@"%d", [event _isKeyDown]);
    NSLog(@"%d", [event _inputFlags]);
    if ([event _isKeyDown] && [[event _unmodifiedInput] isEqualToString:@"s"] && [event _modifierFlags]==206158430208) 
        NSLog(@"Hello");
    

我希望这段代码至少能对需要它的人有所帮助。您可以使用_modifierFlags 确定何时按下命令键、选项键和控制键。我没有玩太多,但似乎是获得事件的好方法。

您可以从http://nacho4d-nacho4d.blogspot.com/2012/01/catching-keyboard-events-in-ios.html 借用代码来改进。如果其他人找到更好的方法,请发布!

由于这是使用私有 API,最好将所有内容包装在 respondsToSelector 中。诸如_unmodifiedInput之类的东西。

我不确定苹果是否会接受实现此功能的应用程序,因此使用风险自负。

【讨论】:

我正在寻找有关 UIKeyCommands 的信息,发现自己在链接中:P【参考方案2】:

在 UIApplication 上重写此方法并玩得开心:)

- (void)handleKeyUIEvent:(UIEvent *)event

    size_t s = malloc_size((__bridge const void *)(event));
    NSLog(@"%s enter... %ld", __func__, s);
//    unsigned char *ptr = (unsigned char *)(__bridge void *)event;

    unsigned long *ptr = (unsigned long *)(__bridge void *)event;
//
//#define OFF_KEY_MASK 12
//#define OFF_KEY_SCANCODE 15
//#define OFF_KEY_CHAR 17

//    NSLog(@"type: %lx off: %d", *(ptr + 2), 2);
//    NSLog(@"MASK: %lx off: %d", *(ptr + OFF_KEY_MASK), OFF_KEY_MASK);
//    NSLog(@"SCAN: %lx off: %d", *(ptr + OFF_KEY_SCANCODE), OFF_KEY_SCANCODE);
//    NSLog(@"CHAR: %lx off: %d", *(ptr + OFF_KEY_CHAR), OFF_KEY_CHAR);

    NSLog(@"sizeof unsigned long: %lx", sizeof(unsigned long));

    for (int i = 0; i < s / 4; ++i) 
//        NSLog(@"... [%d] = %x", i, *(unsigned char *)(ptr + i));
        NSLog(@"... [%d] = %lx", i, *(unsigned long *)(ptr + i));
    

#define OFF_DUMP 8

    unsigned long *dump = (unsigned long *) *(ptr + OFF_DUMP);
    s = malloc_size((const void *)*(ptr + OFF_DUMP));

    NSLog(@"... *[%d] size: %ld", OFF_DUMP, malloc_size((const void *)*(ptr + OFF_DUMP)));

    for (int i = 0; i < s / 4; ++i) 
        NSLog(@"..... [%d] = %lx", i, *(unsigned long *)(dump + i));
    

    struct objc_super super_data =  self, [UIApplication class] ;
    objc_msgSendSuper(&super_data, @selector(handleKeyUIEvent:), event);
//    [super handleKeyUIEvent:event];

【讨论】:

如何在应用程序或主屏幕中捕捉触摸事件? 我无法完全理解你想在哪里捕捉触摸事件的问题?如果您指的是应用程序,则 UIView 中有针对触摸事件的公共回调。但我认为您无法捕获主屏幕上的触摸事件,因为它不属于您的应用程序。 感谢您的回答。我的意思是在越狱设备中捕获事件。 handleKeyUIEvent 是否允许根据 Apple 使用,因为它是私有方法?

以上是关于iOS 7 硬件键盘事件的主要内容,如果未能解决你的问题,请参考以下文章

在 phonegap 中打开软键盘时,未在 ios 7 上触发 showkeyboard/hidekeyboard 事件

Xamarin / iOS - 如何从硬件键盘禁用选项卡键码

如何使用JavaScript捕获iOS上的隐藏键盘事件

iOS键盘事件实现控制

ios 最新系统bug与解决——弹出键盘再收起时,原虚拟键盘位点击事件无效

ios 最新系统bug与解决——弹出键盘再收起时,原虚拟键盘位点击事件无效