iOS - 键盘通知(NSNotificationCenter)

iOS - 键盘通知(NSNotificationCenter)_第1张图片
图片源于网络

键盘通知的基本信息

当键盘弹出时,键盘高度会随着键盘语言变化(中文要高些),在这种情况下一般而言对于界面需要重新布局。这就需要用到键盘通知(NSNotificationCenter)。

  • 键盘通知目前的SDK里总共有如下6个:
UIKIT_EXTERN NSNotificationName const UIKeyboardWillShowNotification __TVOS_PROHIBITED;
UIKIT_EXTERN NSNotificationName const UIKeyboardDidShowNotification __TVOS_PROHIBITED;
UIKIT_EXTERN NSNotificationName const UIKeyboardWillHideNotification __TVOS_PROHIBITED;
UIKIT_EXTERN NSNotificationName const UIKeyboardDidHideNotification __TVOS_PROHIBITED;
// Like the standard keyboard notifications above, these additional notifications include
// a nil object and begin/end frames of the keyboard in screen coordinates in the userInfo dictionary.
UIKIT_EXTERN NSNotificationName const UIKeyboardWillChangeFrameNotification  NS_AVAILABLE_IOS(5_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSNotificationName const UIKeyboardDidChangeFrameNotification   NS_AVAILABLE_IOS(5_0) __TVOS_PROHIBITED;
通知是一种消息机制,addObserver与removeObserver需要在对应的生命周期中成对出现。

在键盘通知(NSNotificationCenter)的userInfo字典中包含了一些键盘frame以及动画相关的信息:

UIKIT_EXTERN NSString *const UIKeyboardFrameBeginUserInfoKey        NS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED; // NSValue of CGRect
UIKIT_EXTERN NSString *const UIKeyboardFrameEndUserInfoKey          NS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED; // NSValue of CGRect
UIKIT_EXTERN NSString *const UIKeyboardAnimationDurationUserInfoKey NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED; // NSNumber of double
UIKIT_EXTERN NSString *const UIKeyboardAnimationCurveUserInfoKey    NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED; // NSNumber of NSUInteger (UIViewAnimationCurve)
UIKIT_EXTERN NSString *const UIKeyboardIsLocalUserInfoKey           NS_AVAILABLE_IOS(9_0) __TVOS_PROHIBITED; // NSNumber of BOOL

// These keys are superseded by UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey.
UIKIT_EXTERN NSString *const UIKeyboardCenterBeginUserInfoKey   NS_DEPRECATED_IOS(2_0, 3_2) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIKeyboardCenterEndUserInfoKey     NS_DEPRECATED_IOS(2_0, 3_2) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIKeyboardBoundsUserInfoKey        NS_DEPRECATED_IOS(2_0, 3_2) __TVOS_PROHIBITED;
  • NSValue: NSValue提供了简单的容器来包含C或Objective-C数据项。可以容纳任何基本数据类型如char,int,float,double,以及指针,结构体和对象ids。NSArray和NSSet集合类对象要求它们的元素为对象类型,NSValue的主要目的是使这些数据类型可以添加至集合中。NSValue对象是不可变类型。 简而言之,NSValue是基本数据类型或自定义数据类型所定义变量的对象包装器。
    注:NSNumber等都是继承于NSValue。(通过NSValueUIGeometryExtensions这个类别封装CGPoint,CGSize,CGRect等结构体)
@interface NSValue (NSValueUIGeometryExtensions)  
  
+ (NSValue *)valueWithCGPoint:(CGPoint)point;  
+ (NSValue *)valueWithCGSize:(CGSize)size;  
+ (NSValue *)valueWithCGRect:(CGRect)rect;  
+ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform;  
+ (NSValue *)valueWithUIEdgeInsets:(UIEdgeInsets)insets;  
+ (NSValue *)valueWithUIOffset:(UIOffset)insets NS_AVAILABLE_IOS(5_0);  
  
- (CGPoint)CGPointValue;  
- (CGSize)CGSizeValue;  
- (CGRect)CGRectValue;  
- (CGAffineTransform)CGAffineTransformValue;  
- (UIEdgeInsets)UIEdgeInsetsValue;  
- (UIOffset)UIOffsetValue NS_AVAILABLE_IOS(5_0);  
  
@end  
  • UIKeyboardFrameBeginUserInfoKey: 动画前键盘的位置,包含CGRect的NSValue
  • UIKeyboardFrameEndUserInfoKey:动画结束后的键盘位置,包含CGRect的NSValue
NSDictionary* info = [aNotification userInfo];  
CGRect rect        =[[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
  • UIKeyboardAnimationDurationUserInfoKey:动画持续时间,数值是NSNumber
  • UIKeyboardAnimationCurveUserInfoKey:动画曲线类型(UIViewAnimationCurve),数值是NSNumber
typedef enum {  
   UIViewAnimationCurveEaseInOut, //淡入淡出,开始时慢,由慢变快,中间最快,然后变慢;  
   UIViewAnimationCurveEaseIn,//淡入,开始时慢然后越来越快;  
   UIViewAnimationCurveEaseOut,//淡出,开始快然后越来越慢;  
   UIViewAnimationCurveLinear//线性匀速,开始和结束是一个速度。  
} UIViewAnimationCurve; 
  • UIKeyboardIsLocalUserInfoKey 是否是原生键盘
  • UIKeyboardCenterBeginUserInfoKey 键盘开始的时候中心点位置
  • UIKeyboardCenterEndUserInfoKey 键盘结束的时候中心点位置
  • UIKeyboardBoundsUserInfoKey:键盘大小
// These keys are superseded by UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey.
翻译:这些钥匙(UIKeyboardCenterBeginUserInfoKey, UIKeyboardCenterEndUserInfoKey, UIKeyboardBoundsUserInfoKey)被UIKeyboardFrameBeginUserInfoKey和UIKeyboardFrameEndUserInfoKey取代。

键盘通知的使用

  • 添加键盘监听事件
#pragma mark -添加键盘监听事件

/**
 添加键盘监听事件
 */
-(void)addNotificationForKeyboard
{
    // 注册键盘通知
    //键盘的frame值将要发生变化
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardWillChangeFrameNotification:) name:UIKeyboardWillChangeFrameNotification object:nil];
    
    //键盘的frame值发生变化
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardDidChangeFrameNotification:) name:UIKeyboardDidChangeFrameNotification object:nil];
    
    // 即将显示
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil];

    // 显示
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardDidShowNotification:) name:UIKeyboardDidShowNotification object:nil];
    // 即将隐藏
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHideNotification:) name:UIKeyboardDidHideNotification object:nil];
    
    // 隐藏
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHideNotification:) name:UIKeyboardDidHideNotification object:nil];

}
  • 移除键盘监听事件
#pragma mark - 移除键盘监听事件
/**
 移除键盘监听事件
 */
- (void)removeNotificationForKeyboard
{
    //键盘的frame值将要发生变化
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
    //键盘的frame值发生变化
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidChangeFrameNotification object:nil];
    // 即将显示
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    // 显示
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
    // 即将隐藏
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
    // 隐藏
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
}
  • 键盘监听方法
#pragma mark -键盘监听方法
- (void) keyboardWillChangeFrameNotification: (NSNotification *)notif{
    NSLog(@"键盘的frame值将要发生变化");
}
- (void) keyboardDidChangeFrameNotification: (NSNotification *)notif{
    NSLog(@"键盘的frame值已经发生变化");
}
- (void) keyboardWillShowNotification: (NSNotification *)notif{
    NSLog(@"键盘即将显示");
}
- (void) keyboardDidShowNotification: (NSNotification *)notif{
    NSLog(@"键盘显示");
}
- (void) keyboardWillHideNotification:(NSNotification *)notif{
    NSLog(@"键盘即将隐藏");
}
- (void) keyboardDidHideNotification:(NSNotification *)notif{
    NSLog(@"键盘隐藏");
}
  • notification 中userInfo的完整信息:
/**
    {
    UIKeyboardAnimationCurveUserInfoKey = 7;
    UIKeyboardAnimationDurationUserInfoKey = "0.25";
    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 796}";
    UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 538}";
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
    UIKeyboardIsLocalUserInfoKey = 1;
    }
    */
  • 键盘通知(NSNotificationCenter)正确使用
    • 在界面即将出现的时候注册键盘通知
    - (void)viewWillAppear:(BOOL)animated {
      [super viewWillAppear:animated]; 
      //注册键盘通知
      [self addNotificationForKeyboard];
     }
    
    • 在页面即将消失的时候移除通知 移除通知要用通知名对应去移除
    - (void)viewWillDisappear:(BOOL)animated {
      [super viewWillDisappear:animated];
      //移除键盘监听
      [self removeNotificationForKeyboard];
    }
    

键盘通知的发出顺序

  • 当一个UITextView或UITextField变成第一焦点时,通知的发出顺序如下:
UIKeyboardWillChangeFrameNotification --> UIKeyboardWillShowNotification --> UIKeyboardDidChangeFrameNotification --> UIKeyboardDidShowNotification
  • 当一个UITextView或UITextField注销焦点状态时,发出通知顺序如下:
UIKeyboardWillChangeFrameNotification -->  UIKeyboardWillHideNotification -->  UIKeyboardDidChangeFrameNotification --> UIKeyboardDidHideNotification
  • 特别需要注意的是,当屏幕旋转的时候也会发出键盘通知,并且顺序如下:
UIKeyboardWillChangeFrameNotification --> UIKeyboardWillHideNotification --> UIKeyboardDidChangeFrameNotification --> UIKeyboardDidHideNotification --> UIKeyboardWillChangeFrameNotification --> UIKeyboardWillShowNotification --> UIKeyboardDidChangeFrameNotification --> UIKeyboardDidShowNotification
 /**
注:其顺序是一个UITextView或UITextField注销焦点状态时,发出键盘通知顺序和一个UITextView或UITextField变成第一焦点时发出键盘顺序组合起来一致,也就是说,在屏幕旋转期间,虽然我们看起来好像键盘没啥变化,但实际上通知已经经理了从“消失”到再次“显示”的路径了。
*/

参考

  • 关于获取键盘通知信息的处理

  • ios SDK开发之键盘通知

  • iOS 键盘通知(NSNotificationCenter)正确使用

你可能感兴趣的:(iOS - 键盘通知(NSNotificationCenter))