2

Just for starters: I'm already listening to keyboard will appear/disappear/change notifications. They're not firing. Neither are did appear/disappear/change.

When I have the keyboard up, and push a controller on top which also has the keyboard up (-[UITextView becomeFirstResponder] in viewWillAppear), no keyboard notifications are fired. This makes some sense, as the keyboard does not actually move in this animation, but it's certainly not desirable in this case.

How would I detect this scenario, and / or how can I get the current position of the keyboard when no notification has been fired? A global, shared listener is an option, but I'd prefer to avoid that if possible.

Groxx
  • 2,489
  • 1
  • 25
  • 32
  • I'm sure that you've seen [this related question](http://stackoverflow.com/a/1492436/335858) already, but in case you didn't, here it is. – Sergey Kalinichenko Aug 03 '12 at 19:02
  • Yeah, that's my backup plan. Though that code snippet is horrible, behavior-wise - seems like nobody checks their behavior with multiple keyboard layouts (Japanese, for instance, is taller than the US keyboard). You can't trust the height to be a consistent value. – Groxx Aug 03 '12 at 19:19
  • Yes, the code there looks like a skeletal sketch of a solution, but it has enough info to build your own. – Sergey Kalinichenko Aug 03 '12 at 19:24

1 Answers1

0

You would need to find the firstResponder, and if its a UITextField or UITextView then the keyboard is up or moving. No notification means its up already, so its old frame (relative to the window) is still valid. Unfortunately there is no easy way to find the firstReponder. I grabbed some code that recursively walked all the current view's subviews, looking for it.

EDIT:

- (UIView *)findFirstResponder
{
    if (self.isFirstResponder) {
        return self;     
    }

    for (UIView *subView in self.subviews) {
        UIView *firstResponder = [subView findFirstResponder];
        if (firstResponder) return firstResponder;
    }
    return nil;
}
David H
  • 40,852
  • 12
  • 92
  • 138
  • Yes, what I do is handle this in viewWillDisappear() handler ... if you have a ViewController with text fields, just do [txtField resignFirstResponder] in viewWillDisappear. – CSmith Aug 03 '12 at 18:30
  • seems like I'd still need some sort of shared global containing the old frame, or use some of the more frightening loop-through-all-views-to-find-keyboard hacks that are crazy fragile to know what the current frame is. Meaning: it's an option, but I'll probably go for the shared 'keyboard state' object over this. – Groxx Aug 03 '12 at 18:39
  • If you look at the window's subviews, isn't the keyboard view there? If so you can get its frame that way. The method to get the first responder isn't so terrible and works well - I use it in my app. Its not like its getting run at critical times and affects performance. – David H Aug 03 '12 at 19:31
  • there's a lot of iOS-version-dependent code in those, depending on how the keyboard is displayed. `if([[keyboard description] hasPrefix:@" – Groxx Aug 03 '12 at 19:55
  • If you do nothing more than save the keyboard size in a global, then you have what you need to compute a frame at any moment. The firstResponder code is vanilla and should be valid indefinitely. I agree I would not go looking for some string match in description! – David H Aug 03 '12 at 20:29