…or take the easy way:
When you enter a textField, it becomes first responder and the keyboard appears.
You can check the status of the keyboard with [myTextField isFirstResponder]
. If it returns YES
, then the the keyboard is active.
drawnonward's code is very close, but collides with UIKit's namespace and could be made easier to use.
@interface KeyboardStateListener : NSObject {
BOOL _isVisible;
}
+ (KeyboardStateListener *)sharedInstance;
@property (nonatomic, readonly, getter=isVisible) BOOL visible;
@end
static KeyboardStateListener *sharedInstance;
@implementation KeyboardStateListener
+ (KeyboardStateListener *)sharedInstance
{
return sharedInstance;
}
+ (void)load
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
sharedInstance = [[self alloc] init];
[pool release];
}
- (BOOL)isVisible
{
return _isVisible;
}
- (void)didShow
{
_isVisible = YES;
}
- (void)didHide
{
_isVisible = NO;
}
- (id)init
{
if ((self = [super init])) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(didShow) name:UIKeyboardDidShowNotification object:nil];
[center addObserver:self selector:@selector(didHide) name:UIKeyboardWillHideNotification object:nil];
}
return self;
}
@end
Create a UIKeyboardListener
when you know the keyboard is not visible, for example by calling [UIKeyboardListener shared]
from applicationDidFinishLaunching
.
@implementation UIKeyboardListener
+ (UIKeyboardListener) shared {
static UIKeyboardListener sListener;
if ( nil == sListener ) sListener = [[UIKeyboardListener alloc] init];
return sListener;
}
-(id) init {
self = [super init];
if ( self ) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(noticeShowKeyboard:) name:UIKeyboardDidShowNotification object:nil];
[center addObserver:self selector:@selector(noticeHideKeyboard:) name:UIKeyboardWillHideNotification object:nil];
}
return self;
}
-(void) noticeShowKeyboard:(NSNotification *)inNotification {
_visible = true;
}
-(void) noticeHideKeyboard:(NSNotification *)inNotification {
_visible = false;
}
-(BOOL) isVisible {
return _visible;
}
@end
I think you need to use the notifications that are provided about the keyboard:
From: http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITextField_Class/Reference/UITextField.html
Keyboard Notifications
When the system shows or hides the keyboard, it posts several keyboard notifications. These notifications contain information about the keyboard, including its size, which you can use for calculations that involve moving views. Registering for these notifications is the only way to get some types of information about the keyboard. The system delivers the following notifications for keyboard-related events:
* UIKeyboardWillShowNotification * UIKeyboardDidShowNotification * UIKeyboardWillHideNotification * UIKeyboardDidHideNotification
For more information about these notifications, see their descriptions in UIWindow Class Reference. For information about how to show and hide the keyboard, see Text and Web.
Add an extension
extension UIApplication {
/// Checks if view hierarchy of application contains `UIRemoteKeyboardWindow` if it does, keyboard is presented
var isKeyboardPresented: Bool {
if let keyboardWindowClass = NSClassFromString("UIRemoteKeyboardWindow"),
self.windows.contains(where: { $0.isKind(of: keyboardWindowClass) }) {
return true
} else {
return false
}
}
}
Then check if keyboard is present,
if UIApplication.shared.isKeyboardPresented {
print("Keyboard presented")
} else {
print("Keyboard is not presented")
}
Swift 3 Implementation
import Foundation
class KeyboardStateListener: NSObject
{
static let shared = KeyboardStateListener()
var isVisible = false
func start() {
NotificationCenter.default.addObserver(self, selector: #selector(didShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func didShow()
{
isVisible = true
}
func didHide()
{
isVisible = false
}
}
Using the window subview hierarchy as indication for keyboard showing is a hack. If Apple changers their underlying implementation all these answers would break.
The correct way would be to monitor Keyboard show and hide notifications application wide such as inside your App Delegate:
In AppDelegate.h:
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (assign, nonatomic) BOOL keyboardIsShowing;
@end
In AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Monitor keyboard status application wide
self.keyboardIsShowing = NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
return YES;
}
- (void)keyboardWillShow:(NSNotification*)aNotification
{
self.keyboardIsShowing = YES;
}
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
self.keyboardIsShowing = NO;
}
Then you can check using:
BOOL keyboardIsShowing = ((AppDelegate*)[UIApplication sharedApplication].delegate).keyboardIsShowing;
It should be noted the keyboard show/hide notifications will not fire when user is using a bluetooth or external keyboard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With