欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

IOS 学习笔记 UITextView UITextField 协议

程序员文章站 2022-05-14 13:05:18
...

目录

1 UITextView & UITextField

1.1 UITextView

1.2 UITextField

2 Delegate

2.1 UITextViewDelegate

2.2 UITextFieldDelegate

3 UITextView 和 UITextViewDelegate

3.1 Interface Builder实现

3.2 通过代码添加

4 UITextField 和 UITextFieldDelegate

5 Button的点击事件

5.1 添加UIButton并添加引用

5.2 代码分析


1 UITextView & UITextField

 

1.1 UITextView

UITextView显示多行文本视图,接受编辑输入,类似于文本编辑器,获取焦点的时候会从底部弹出软键盘输入

IOS 学习笔记 UITextView UITextField 协议

 

1.2 UITextField

UITextField类似输入框,比如可用作search输入框,接受文本输入,获取焦点的时候会从底部弹出软键盘输入

如下图

IOS 学习笔记 UITextView UITextField 协议

 

2 Delegate

Delegate委托协议,有点类似于对接口类的实现,比如Android中Activity实现View.OnClickListener,当有Class实现了View.OnClickListener,那么就需要实现其接口方法onClick(View v),这里Delegate中也会存在相应的回调函数,比如UITextViewDelegate和UITextFieldDelegate各字都有自己可回调的函数。这是通过协议的方式给视图添加回调是IOS的特色。

 

2.1 UITextViewDelegate

UITextViewDelegate源码


@protocol UITextViewDelegate <NSObject, UIScrollViewDelegate>

@optional

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;
- (BOOL)textViewShouldEndEditing:(UITextView *)textView;

- (void)textViewDidBeginEditing:(UITextView *)textView;
- (void)textViewDidEndEditing:(UITextView *)textView;

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
- (void)textViewDidChange:(UITextView *)textView;

- (void)textViewDidChangeSelection:(UITextView *)textView;

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction NS_AVAILABLE_IOS(10_0);
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction NS_AVAILABLE_IOS(10_0);

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithTextAttachment:inRange:forInteractionType: instead");

@end

从上面源码中可以看到UITextViewDelegate中包含了

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;

- (void)textViewDidChange:(UITextView *)textView;

- (void)textViewDidChangeSelection:(UITextView *)textView;

等一系列的回调函数,虽然没有给说明,但是函数名称却很清楚的表明了自己的作用。

 

 

2.2 UITextFieldDelegate

UITextFieldDelegate源码


@protocol UITextFieldDelegate <NSObject>

@optional

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;        // return NO to disallow editing.
- (void)textFieldDidBeginEditing:(UITextField *)textField;           // became first responder
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;          // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
- (void)textFieldDidEndEditing:(UITextField *)textField;             // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
- (void)textFieldDidEndEditing:(UITextField *)textField reason:(UITextFieldDidEndEditingReason)reason NS_AVAILABLE_IOS(10_0); // if implemented, called in place of textFieldDidEndEditing:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;   // return NO to not change text

- (BOOL)textFieldShouldClear:(UITextField *)textField;               // called when clear button pressed. return NO to ignore (no notifications)
- (BOOL)textFieldShouldReturn:(UITextField *)textField;              // called when 'return' key pressed. return NO to ignore.

@end

从源码中可以看到

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;        // return NO to disallow editing.等8个回调函数

分别在用户和UITextView进行交互的各个阶段被回调。后面的注释写的很清楚,比如textFieldShouldReturn函数会在视图UITextView接受输入后,软件盘的return键被按下的时候回调。

 

3 UITextView 和 UITextViewDelegate

要给UITextView添加响应事件可以通过UITextViewDelegate协议来进行,那么怎样将UITextView的响应事件同UITextViewDelegate的回调函数相关连起来呢?注意如果不关联是无法回调到对应的函数的。

 

这里有两种方式:Interface Builder、代码实现

3.1 Interface Builder实现

通过在xcode中拖拽(Interface Builder实现,这样说不易于理解,因为刚开始学习,对这Interface Builder概念可能不了解),如下图

见鼠标放在UITextField或者UITextView,右键点击(mac触摸板是双指点击)弹出对话框,选择delegate,将光标点按在后面⭕️上,这时候⭕️中间会出现一个“+”,然后拖拽到右边的View Controller上,这时候View Controller上会有一个蓝色这框表示它被选中了,然后松手

(这里不好截图操作,我就直接画出来的)

IOS 学习笔记 UITextView UITextField 协议

经过上面操作,弹出的选项对话框delegate选项后面的空心圆圈就变成实心了,如下图,表示delegate和View Controller建立了绑定关系

IOS 学习笔记 UITextView UITextField 协议

上面用的是UITextField做的例子,UITextView是相同操作

 

下面是实例,

源码代码如下

#import "ViewController.h"

@interface ViewController ()<UITextFieldDelegate, UITextViewDelegate>

@property (weak, nonatomic) IBOutlet UITextView *textView;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet UIButton *button;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}



#pragma mark -- 实现 UITextViewDelegate委托协议中一个方法,当UITextView中文字输入有变化的时候会被调用
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    
    NSLog(@"textView 被调用了,变化的部分是 %@", text);

    return YES;
}

@end

界面如下:

IOS 学习笔记 UITextView UITextField 协议

然后通过拖拽的方法将UITextView的delegate同View Controller联系起来,我们可以看到在源码中便没有相关的代码表明UITextViewDelegate协议和UITextView绑定起来了,这都是xcode帮我实现了,到目前的为止我们主观上是看不到任何线索的,但是背后毋庸置疑肯定会有对应的代码将之相关联,这里暂时不做深究。

 

当我们在TextView中输入abc的时候控制台会有打印如下:

2019-04-12 21:53:28.979854+0800 TextView_TextField[12595:439931] textView 被调用了,变化的部分是 a
2019-04-12 21:53:29.616090+0800 TextView_TextField[12595:439931] textView 被调用了,变化的部分是 b
2019-04-12 21:53:30.099341+0800 TextView_TextField[12595:439931] textView 被调用了,变化的部分是 c
2019-04-12 21:56:11.521134+0800 TextView_TextField[12595:439931] textView 被调用了,变化的部分是 
2019-04-12 21:56:11.944165+0800 TextView_TextField[12595:439931] textView 被调用了,变化的部分是 
2019-04-12 21:56:12.281370+0800 TextView_TextField[12595:439931] textView 被调用了,变化的部分是 

因为textview函数中有:

NSLog(@"textView 被调用了,变化的部分是 %@", text);

text会取出变化的字符,这里是一个个字母输入的,但是如果我们删除,显示的其实是空字符,函数中很清楚,text是replacementText

 

 

3.2 通过代码添加

上面掩饰了通过非代码的方式让UITextView 和 UITextViewDelegate相关联,然后UITextViewDelegate中的某一个回调函数被调用了,下面将通过代码的方式将让UITextView 和 UITextViewDelegate相关联,

 

1)首先取消掉UITextView 和 UITextViewDelegate的的关系

选中Main.storyboard中的TextView,mac触摸板双指点击弹出如下选择框,点击红色小框中的X,取消掉绑定关系

IOS 学习笔记 UITextView UITextField 协议

2)在代码中添加UITextView 和 UITextViewDelegate的关联关系

这句话将UITextView和UITextViewDelegate协议关联:self.textView.delegate = self;

可以前后做一下对比实验,去掉这句话之后看在控制台是否有对应的输出


#import "ViewController.h"

@interface ViewController ()<UITextFieldDelegate, UITextViewDelegate>

@property (weak, nonatomic) IBOutlet UITextView *textView;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    forControlEvents:UIControlEventTouchDown];
    self.textView.delegate = self;//这句话将UITextView和UITextViewDelegate协议关联
    self.textField.delegate = self;//这句话将UITextField和UITextFieldDelegate协议关联
}

#pragma mark -- 实现 UITextViewDelegate委托协议中一个方法,当UITextView中文字输入有变化的时候会被调用
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSLog(@"textView 被调用了,变化的部分是 %@", text);
    return YES;
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    NSLog(@"UITextField retrun 按键被调用了");
    return YES;
}



@end

输出结果


2019-04-12 22:15:19.800323+0800 TextView_TextField[12832:448693] textView 被调用了,变化的部分是 o
2019-04-12 22:15:19.923160+0800 TextView_TextField[12832:448693] textView 被调用了,变化的部分是 k
2019-04-12 22:15:24.377870+0800 TextView_TextField[12832:448693] UITextField retrun 按键被调用了

4 UITextField 和 UITextFieldDelegate

同上,这里就不做赘述了。

 

5 Button的点击事件

上面类似于,在android中将一个Button和其点击事件的回调函数连接起来,只不过IOS使用了协议来实现,具体内在的关联,以后在分析,看起来似乎没有android中的直观和简单,

mButton.setOnClickListener(this);//this表示当前实现了View.OnClickListener的Class,
//或者直接
mButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        
    }
});

也就是通过setOnClickListener函数给对应的view设置一个回调兼听监听即可。这里类比Android

 

5.1 添加UIButton并添加引用

那么在IOS开发中使用OC是怎么给一个UIView添加事件的呢?

1)在故事板中添加一个UIButton如下图

IOS 学习笔记 UITextView UITextField 协议

 

2)然后在ViewController.m中添加UIButton的引用

有两种方式

方式一

先在代码中手写@property (weak, nonatomic) IBOutlet UIButton *button;然后将其前面的小圆圈

这句话需要跟故事板中的Button绑定起来,通过拖拽的连线的方式,选中上面添加的代码前的小圆点到故事板中的button视图,如下图:

IOS 学习笔记 UITextView UITextField 协议

方式二

让xcode自动生成,按住control键,按照下图的箭头的路线拖拽到小框的位置,只要在@interface ViewController和@end之间即可,不一定非要是图中小红框标示的位置,然后在Name框后面输入,比如button,然后点击Connect按钮,就会自动生成方法一中手写的代码

IOS 学习笔记 UITextView UITextField 协议

下面是通过代码使用button

#import "ViewController.h"

@interface ViewController ()<UITextFieldDelegate, UITextViewDelegate>

@property (weak, nonatomic) IBOutlet UITextView *textView;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet UIButton *button;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    [self.button addTarget:self action:@selector(onButtonClick) forControlEvents:UIControlEventTouchDown];

}

-(void)onButtonClick{
    NSLog(@"########## onButtonClick ");
}




@end

 

5.2 代码分析

[self.button addTarget:self action:@selector(onButtonClick) forControlEvents:UIControlEventTouchDown];
上面代码便是给button添加了一个action,这个action的函数名是onButtonClick,注意一定要写成@selector(onButtonClick) 这里的onButtonClick不带入参

这里就简单的举例,至于@selector(onButtonClick)等函数为什么要这样写 以后在说明,这里先大概了解,有个整体把握。