本文章介绍委托(delegation)和UITextField的使用。委托是Cocoa Touch中一种常见的设计模式。
一:继续上一篇博客,了解一下UITextField
它可以接受用户的输入文本,例如在相关页面中需要与用户进行数据交互时,使用到的UI组件。
- (void)loadView
{
CGRect frame = [UIScreen mainScreen].bounds;
BNRHypnosisView *backgroundView = [[BNRHypnosisView alloc] initWithFrame:frame];
CGRect textFieldRect = CGRectMake(40,70,240,30);
UITextField* textField = [[UITextField alloc] initWithFrame:textFieldRect];
// 设置UITextField对象的边框样式,便于查看它在屏幕上的位置
textField.borderStyle = UITextBorderStyleRoundedRect;
[backgroundView addSubview:textField];
self.view = backgroundView;
}
当我们点击文本框,进行填写内容。为了理解UITextField对象对点击事件的响应过程,下面介绍第一响应者(first responder)的概念。
二:UIResponder
UIResponder是UIKit框架中的一个抽象类。它的几个子类:UIView UIVieController UIApplication 。其中UIResponder定义了一系列方法,用于接受和处理用户事件,例如:触摸事件,运动事件(摇晃),功能控制事件(编辑文本或者播放音乐)。UIResponder的子类会覆盖这些方法,实现自己的事件响应代码。
触摸事件应该由被触摸的视图负责处理。系统会将触摸事件直接发送给被触摸的视图,下一篇博客将详细介绍触摸事件。而其他类型的事件都是由第一响应者负责处理,其中UIWindow有一个firstResponder属性指向第一响应者。例如当用户点击UITextField对象时,UITextField对象就会成为第一响应者。UIWindow会将firstresponder指向该对象,之后,如果应用接收到运动事件或者功能控制事件,都会发送给UITextField对象。
某个UITextField成为第一响应者时,屏幕上会弹出键盘。
成为第一响应者:代码中向对象发送becomeFirstResponder消息,使其成为第一响应者 | |
相反如果向关闭键盘,可以向UITextField对象发送resignFirstResponder消息,解除第一响应者 |
三:委托和UITextField的占位符
textField.placeholder = @"灰色提示值";//现在UITextField对象中有一行占位符文本,当用户在UITextField对象中输入文字时,站位符文本就会消失。
textField.returnKeyType = UIReturnKeyDone;//同时换行键不再显示默认的Return,而是Done。
如果点击Done键发现没有什么不同,实际上,修改换行键的类型只是改变了换行键的外观,如果要实现用户点击换行键后的功能,必须编写响应的代码。
autocapitalizationType | 设置UITextField对象的自动大写功能,包括none(关闭自动大写),words(单词),句子,所有的字母,四种类型。 |
autocorrectionType | 启用/禁用(YES/NO)UITextField的拼写建议功能,可以提示用户输错的单词,并建议修改。 |
enableReturnkeyAutomatically | 换行键是否启用 |
keyboardType | 设置UITEXTField对象弹出的键盘类型 |
secureTextEntry | 启动/禁用UITextField对象的安全输入功能。如果设置为YES,会以圆点代替用户输入的文字 |
什么是委托呢?
目标 —— 动作(Target - Action)设计模式:当某个特定的事件发生时(例如按下按钮),发生事情的一方会向指定的目标对象发出一个之前设定好的动作消息。
针对不同的事件,需要创建不同的动作消息。UIButton对象的事件比较简单,通常只需要处理点击事件,反之,像UITextField这样的复杂的对象,Apple使用委托设计模式。UITextField对象具有一个委托属性通过为UITextField设置委托,UITextField对象会在发生事件时向委托发送相应消息,有委托处理该事件。
注意在委托方法中,通常将对象自身作为第一个参数。多个对象可能具有相同的委托,当委托接受到消息时,需要根据该参数判断发送该消息的对象。例如下面的操作:将UITextField对象所位于的视图控制器 ——BNRHyponsisViewController设置为它的委托,并实现textFieldShouldReturn:委托方法,当用户点击Done按钮时,UITextField对象就会调用该方法。
在loadView中
//1.设置委托
textField.delegate = self;
//实现委托所必须的功能方法:requie
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
NSLog(@"%@",textField.text);
return YES;
}
Controller中不需要实现UITextField对象的所有委托方法,UITextField对象会在运行时检查委托是否实现了某个方法,如果没有实现某个方法,UITextField对象就不会调用该方法。
四:协议
凡是支持委托的对象,其背后都有一个相应的协议(接口)
声明协议的方法:
@interface Controller()<协议名>
协议不是类,只是一组方法声明。不能为协议创建对象,或者添加实例变量,协议自身不实现方法,需要由遵守相应协议的类实现。发送发在发送可选方案之前,先向其委托另一个名为respondsToSelector:的消息,所有的Object-C对象都从NSObject继承了该方法,该方法能在运行时检查对象是否实现了指定的方法。@selector()指令可以将选择器(selector)转换成数值,可以作为参数传递。例如TextField可以实现如下方法:
- (void) clearButtonTapped
{
//TextFieldShouldClear:是可选方法,需要先检查委托是否实现了该方法
SEL clearSelector = @selector(tetFieldShouldClear:);
if([self.delegate respondsToSelector:clearSelector])
{
if([self.delegate textFieldShouldClear:self]){
self.text = @"";
}
}
}
//如果某个方法是必须的,那么发送方可以直接向其委托对象发送相应的消息,不用检查委托对象是否实现了该方法。这意味着,如果委托对象没有实现相应的 方法,应用就会抛出未知选择器异常,导致应用崩溃。