关注仓库,及时获得更新:iOS-Source-Code-Analyze
Follow: Draveness · Github
这篇文章会对 IQKeyboardManager 自动解决键盘遮挡问题的方法进行分析。
最近在项目中使用了 IQKeyboardManager 来解决 UITextField
被键盘遮挡的问题,这个框架的使用方法可以说精简到了极致,只需要将 IQKeyboardManager
加入 Podfile
,然后 pod install
就可以了。
1 |
pod 'IQKeyboardManager' |
这篇文章的题目《零行代码解决键盘遮挡问题》来自于开源框架的介绍:
Codeless drop-in universal library allows to prevent issues of keyboard sliding up and cover UITextField/UITextView. Neither need to write any code nor any setup required and much more.
因为在项目中使用了 IQKeyboardManager,所以,我想通过阅读其源代码来了解这个黑箱是如何工作的。
虽然这个框架的实现的方法是比较简单的,不过它的实现代码不是很容易阅读,框架因为包含了很多与 UI 有关的实现细节,所以代码比较复杂。
架构分析
说是架构分析,其实只是对 IQKeyboardManager 中包含的类以及文件有一个粗略地了解,研究一下这个项目的层级是什么样的。
整个项目中最核心的部分就是 IQKeyboardManager
这个类,它负责管理键盘出现或者隐藏时视图移动的距离,是整个框架中最核心的部分。
在这个框架中还有一些用于支持 IQKeyboardManager 的分类,以及显示在键盘上面的 IQToolBar:
使用红色标记的部分就是 IQToolBar
,左侧的按钮可以在不同的 UITextField
之间切换,中间的文字是 UITextField.placeholderText
,右边的 Done
应该就不需要解释了。
这篇文章会主要分析 IQKeyboardManager
中解决的问题,会用小篇幅介绍包含占位符(Placeholder) IQTextView
的实现。
IQTextView 的实现
在具体研究如何解决键盘遮挡问题之前,我们先分析一下框架中最简单的一部分 IQTextView
是如何为 UITextView
添加占位符的。
1 2 3 |
@interface IQTextView : UITextView @end |
IQTextView
继承自 UITextView
,它只是在 UITextView
上添加上了一个 placeHolderLabel
。
在初始化时,我们会为 UITextViewTextDidChangeNotification
注册通知:
1 2 3 |
- (void)initialize { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshPlaceholder) name:UITextViewTextDidChangeNotification object:self]; } |
在每次 UITextView 中的 text 更改时,就会调用 refreshPlaceholder
方法更新 placeHolderLabel
的 alpha
值来隐藏或者显示 label:
1 2 3 4 5 6 7 8 9 10 |
-(void)refreshPlaceholder { if ([[self text] length]) { [placeHolderLabel setAlpha:0]; } else { [placeHolderLabel setAlpha:1]; } [self setNeedsLayout]; [self layoutIfNeeded]; } |
IQKeyboardManager
下面就会进入这篇文章的正题:IQKeyboardManager
。
如果你对 iOS 开发比较熟悉,可能会发现每当一个类的名字中包含了 manager
,那么这个类可能可能遵循单例模式,IQKeyboardManager
也不例外。
IQKeyboardManager 的初始化
当 IQKeyboardManager
初始化的时候,它做了这么几件事情:
- 监听有关键盘的
123[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil]; - 注册与 UITextField 以及 UITextView 有关的通知
1234567[self registerTextFieldViewClass:[UITextField class]didBeginEditingNotificationName:UITextFieldTextDidBeginEditingNotificationdidEndEditingNotificationName:UITextFieldTextDidEndEditingNotification];[self registerTextFieldViewClass:[UITextView class]didBeginEditingNotificationName:UITextViewTextDidBeginEditingNotificationdidEndEditingNotificationName:UITextViewTextDidEndEditingNotification];- 调用的方法将通知绑定到了
textFieldViewDidBeginEditing:
和textFieldViewDidEndEditing:
方法上
16177 aligncenter" src="http://jbcdn2.b0.upaiyun.com/2016/06/85cc99639a8a8519638a22ca33ee9c84.png" alt="icon">Icon这篇文章会对 IQKeyboardManager 自动解决键盘遮挡问题的方法进行分析。
最近在项目中使用了 IQKeyboardManager 来解决
UITextField
被键盘遮挡的问题,这个框架的使用方法可以说精简到了极致,只需要将IQKeyboardManager
加入Podfile
,然后pod install
就可以了。1pod 'IQKeyboardManager'这篇文章的题目《零行代码解决键盘遮挡问题》来自于开源框架的介绍:
Codeless drop-in universal library allows to prevent issues of keyboard sliding up and cover UITextField/UITextView. Neither need to write any code nor any setup required and much more.
因为在项目中使用了 IQKeyboardManager,所以,我想通过阅读其源代码来了解这个黑箱是如何工作的。
虽然这个框架的实现的方法是比较简单的,不过它的实现代码不是很容易阅读,框架因为包含了很多与 UI 有关的实现细节,所以代码比较复杂。
架构分析
说是架构分析,其实只是对 IQKeyboardManager 中包含的类以及文件有一个粗略地了解,研究一下这个项目的层级是什么样的。
整个项目中最核心的部分就是
IQKeyboardManager
这个类,它负责管理键盘出现或者隐藏时视图移动的距离,是整个框架中最核心的部分。在这个框架中还有一些用于支持 IQKeyboardManager 的分类,以及显示在键盘上面的 IQToolBar:
使用红色标记的部分就是
IQToolBar
,左侧的按钮可以在不同的UITextField
之间切换,中间的文字是UITextField.placeholderText
,右边的Done
应该就不需要解释了。这篇文章会主要分析
IQKeyboardManager
中解决的问题,会用小篇幅介绍包含占位符(Placeholder)IQTextView
的实现。IQTextView 的实现
在具体研究如何解决键盘遮挡问题之前,我们先分析一下框架中最简单的一部分
IQTextView
是如何为UITextView
添加占位符的。123@interface IQTextView : UITextView@endIQTextView
继承自UITextView
,它只是在UITextView
上添加上了一个placeHolderLabel
。在初始化时,我们会为
UITextViewTextDidChangeNotification
注册通知:123- (void)initialize {[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshPlaceholder) name:UITextViewTextDidChangeNotification object:self];}在每次 UITextView 中的 text 更改时,就会调用
refreshPlaceholder
方法更新placeHolderLabel
的alpha
值来隐藏或者显示 label:12345678910-(void)refreshPlaceholder {if ([[self text] length]) {[placeHolderLabel setAlpha:0];} else {[placeHolderLabel setAlpha:1];}[self setNeedsLayout];[self layoutIfNeeded];}IQKeyboardManager
下面就会进入这篇文章的正题:
IQKeyboardManager
。如果你对 iOS 开发比较熟悉,可能会发现每当一个类的名字中包含了
manager
,那么这个类可能可能遵循单例模式,IQKeyboardManager
也不例外。IQKeyboardManager 的初始化
当
IQKeyboardManager
初始化的时候,它做了这么几件事情:- 监听有关键盘的
123[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil]; - 注册与 UITextField 以及 UITextView 有关的通知
1234567[self registerTextFieldViewClass:[UITextField class]didBeginEditingNotificationName:UITextFieldTextDidBeginEditingNotificationdidEndEditingNotificationName:UITextFieldTextDidEndEditingNotification];[self registerTextFieldViewClass:[UITextView class]didBeginEditingNotificationName:UITextViewTextDidBeginEditingNotificationdidEndEditingNotificationName:UITextViewTextDidEndEditingNotification];- 调用的方法将通知绑定到了
textFieldViewDidBeginEditing:
和textFieldViewDidEndEditing:
方法上
- 调用的方法将通知绑定到了
- 监听有关键盘的
- 调用的方法将通知绑定到了