iOS - 键盘通知(NSNotificationCenter)

图片源于网络

键盘通知的基本信息

当键盘弹出时,键盘高度会随着键盘语言变化(中文要高些),在这种情况下一般而言对于界面需要重新布局。这就需要用到键盘通知(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变成第一焦点时发出键盘顺序组合起来一致,也就是说,在屏幕旋转期间,虽然我们看起来好像键盘没啥变化,但实际上通知已经经理了从“消失”到再次“显示”的路径了。
*/

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容