美文网首页
iOS - 键盘通知(NSNotificationCenter)

iOS - 键盘通知(NSNotificationCenter)

作者: SkyMing一C | 来源:发表于2017-11-14 09:03 被阅读231次
    图片源于网络

    键盘通知的基本信息

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

          本文链接:https://www.haomeiwen.com/subject/wcibmxtx.html