Receive iPhone keyboard events
Asked Answered
M

3

7

Is there anyway to trap all keyboard events across my application? I need to know if user is entering anything using keyboard across my application (Application has multiple views). I was able to capture touchEvents by subclassing UIWindow but unable to capture keyboard events.

Mapping answered 12/8, 2009 at 17:28 Comment(0)
W
14

Use NSNotificationCenter

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(keyPressed:) name: UITextFieldTextDidChangeNotification object: nil];

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(keyPressed:) name: UITextViewTextDidChangeNotification object: nil];

........

-(void) keyPressed: (NSNotification*) notification
{
  NSLog([[notification object]text]);
}
Walworth answered 13/8, 2009 at 6:46 Comment(0)
B
12

I wrote about catching events using a little hack of UIEvent in my Blog

Please refer to : Catching Keyboard Events in iOS for details.

From the above mentioned blog:

The trick is in accessing GSEventKey struct memory directly and check certain bytes to know the keycode and flags of the key pressed. Below code is almost self explanatory and should be put in your UIApplication subclass.

#define GSEVENT_TYPE 2
#define GSEVENT_FLAGS 12
#define GSEVENTKEY_KEYCODE 15
#define GSEVENT_TYPE_KEYUP 11

NSString *const GSEventKeyUpNotification = @"GSEventKeyUpHackNotification";

- (void)sendEvent:(UIEvent *)event
{
    [super sendEvent:event];

    if ([event respondsToSelector:@selector(_gsEvent)]) {

        // Key events come in form of UIInternalEvents.
        // They contain a GSEvent object which contains 
        // a GSEventRecord among other things

        int *eventMem;
        eventMem = (int *)[event performSelector:@selector(_gsEvent)];
        if (eventMem) {

            // So far we got a GSEvent :)

            int eventType = eventMem[GSEVENT_TYPE];
            if (eventType == GSEVENT_TYPE_KEYUP) {

                // Now we got a GSEventKey!

                // Read flags from GSEvent
                int eventFlags = eventMem[GSEVENT_FLAGS];
                if (eventFlags) { 

                    // This example post notifications only when 
                    // pressed key has Shift, Ctrl, Cmd or Alt flags

                    // Read keycode from GSEventKey
                    int tmp = eventMem[GSEVENTKEY_KEYCODE];
                    UniChar *keycode = (UniChar *)&tmp;

                    // Post notification
                    NSDictionary *inf;
                    inf = [[NSDictionary alloc] initWithObjectsAndKeys:
                      [NSNumber numberWithShort:keycode[0]],
                      @"keycode",
                      [NSNumber numberWithInt:eventFlags], 
                      @"eventFlags",
                      nil];
                    [[NSNotificationCenter defaultCenter] 
                        postNotificationName:GSEventKeyUpNotification 
                                      object:nil
                                    userInfo:userInfo];
                }
            }
        }
    }
}
Buckish answered 14/1, 2012 at 14:28 Comment(4)
Please see "How could I write my answer that links to an external resource properly?".Lazarolazaruk
I don't understand what I got -1. Yes, the link is to a post of my blog but it fully answers this question. It catches ALL keyboard events including Shift, Cmd, Ctrl, Alt. If it is because of the use of Private APIs, I clearly stated it is a hack. I am not tricking anybody here.Buckish
Probably because your answer does not answer the question, it simply points to an external source which can disappear, get broken or simply change beyond this question. As Anna Lear points out, read the section she pointed to. The answer point to the following as being the proper rules to follow: - you paraphrase the content of the linked item (possibly omitting details or examples) - you identify the author (yourself, MSDN, etc) - someone could benefit from the answer without reading the linked item at all - you include information to let the reader decide if clicking the link is worthwhileTrachoma
Maybe not a well formed answer, but this this is exactly what I was looking for. Thanks.Am
A
2

Not a simple answer, but I think you have two approaches available.

  1. subclass the input components (UITextView, UITextField, etc) as you've done with the UIWindow.

  2. Create a application wide UITextViewDelegate (and UITextFieldDelegate) and assign all your input field delegates to it.

Adlare answered 12/8, 2009 at 18:11 Comment(1)
This is little tricky now and involves lots of work. I was hoping to see some App level event to captureMapping

© 2022 - 2024 — McMap. All rights reserved.