一些观察:
单例对象的推荐模式如下。 dispatch_once 确保类以线程安全的方式初始化一次,并且静态变量在外部不可见。而且它是标准的 GCD,所以不需要了解 Objective-C 的底层细节。
+ (KeyboardStateListener *)sharedInstance
{
static KeyboardStateListener* shared;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[KeyboardStateListener alloc] init];
// Other initialisations
});
return shared;
}
通常您不想只知道键盘是否可见,而是要知道它有多大。键盘并非都具有相同的尺寸。 iPhone 键盘比 iPad 键盘小。因此,您需要另一个属性 @property (readonly, nonatomic) CGRect keyboardRect;,它在 noticeShowKeyboard: 方法中设置,如下所示:
NSValue* value = notification.userInfo [UIKeyboardFrameEndUserInfoKey];
_keyboardRect = value.CGRectValue;
重要的是要注意矩形在 UIWindow 坐标中并且不考虑屏幕旋转。所以调用者会通过调用来转换那个矩形
KeyboardStateListener* listener = [KeyboardStateListener sharedInstance];
CGRect windowRect = listener.keyboardRect;
CGRect viewRect = [myView convertRect:windowRect fromView:self.window];
如果用户在键盘可见时旋转屏幕,应用程序将被告知键盘已隐藏,然后再次显示。显示时,其他视图很可能尚未旋转。因此,如果您自己观察键盘隐藏/显示事件,请在实际需要时转换坐标,而不是在通知中。
如果用户拆分或取消固定键盘,或使用硬件键盘,通知将始终将键盘显示为隐藏。取消停靠或合并键盘将发送“显示键盘”通知。
监听器必须在键盘隐藏时初始化,否则会错过第一个通知,当键盘不隐藏时会认为键盘是隐藏的。
所以知道你真正想要什么是非常重要的。此代码可用于将东西移出键盘(使用拆分或未停靠的键盘,这是用户的责任)。它不会告诉您用户是否可以在屏幕上看到键盘(在拆分键盘的情况下)。它不会告诉您用户是否可以键入(例如,当有硬件键盘时)。如果应用程序自己创建其他窗口,则查看其他窗口不起作用。