2013-09-11 4 views
4

Теперь, когда у нас есть iOS 7, Apple, очевидно, удалила возможность получать уведомления о клавиатуре от -sendEvent:. Это огромная боль для людей, которые хотят написать что-то, что захватывает все ключевые события и отправляет их на удаленный компьютер, E.G. клиент VNC. UIKeyCommand не обеспечивает необходимую функциональность. В Apple есть много отчетов об ошибках, но они не будут слушать. Отчет об ошибке apple закрывает все отчеты, так как дубликат: rdar: // 14129420.iOS 7 Hardware Keyboard Events

Какое оптимальное решение для этого?

ответ

5

Я, по крайней мере, смог вернуть эти события по частному 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.

Я не уверен, что яблоко примет приложение, которое реализует это, поэтому используйте на свой страх и риск.

+1

Я искал информацию о UIKeyCommands и оказался в ссылке: P – nacho4d

4

Override этот метод на 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]; 
} 
+0

Как поймать события прикосновения в приложениях или в столе? – Suge

+0

Я не могу полностью понять ваш вопрос о том, где вы хотите поймать события касания? Если вы имели в виду приложение, в UIView есть публичные обратные вызовы для событий касания. Но я не думаю, что вы можете поймать события касания, которые находятся на главном экране, поскольку они не принадлежат вашим приложениям. –

+0

Благодарим вас за ответ. Я имею в виду уловить события в джейлбрейк-устройстве. – Suge