办理Text fields和Text views
Text fields和Text views有两个首要功能:显现文本和允许输入和修改文本。
一些编程任务,包括装备文本方针、拜访当时文本、验证用户输入的内容,以及在Text fields中显现掩盖视图(如书签按钮)。UITextField或UITextView方针的Delegate担任大多数这些任务。Delegate有必要采用UITextFieldDelegate或UITextViewDelegate协议,并完成一个或多个协议办法。所有协议办法的完成都是可选的。要调用这些办法,有必要以编程办法或在Interface Builder中设置Text fields和Text views的Delegate特点。
发送给Delegate的音讯序列
在大多数情况下,关于一个文本方针(Text object),榜首呼应者(First-responder)状况有改变(或即将发生改变)时,UITextField或UITextView类的实例,向它们的托付发送一系列类似命名的音讯。当用户点击文本方针时,它自动成为榜首呼应者;因此,系统显现键盘,并开端为该文本方针进行修改会话。当用户点击另一个文本方针或点击按钮结束修改时,当时文本方针将退出榜首呼应者状况。假如没有挑选其他文本方针,则系统躲藏键盘;另一方面,假如用户挑选了另一个文本方针,它将成为榜首呼应者,并显现该方针的键盘。
这种常见的行为也有一些破例。在iPad上,假如View controller运用“form sheet”款式模态地显现其视图,键盘一旦显现,就不会躲藏,直到用户点击dismiss键或模态View controller以编程办法封闭。这种行为的意图是避免当用户在视图之间移动时产生过多的动画,这些视图大部分是Text fields,但不是全部。另一个破例涉及自定义输入视图(Input view)。输入视图是分配给Text view或自定义视图的inputView特点的系统键盘的替代品。当有输入视图时,即使文本方针是榜首呼应程序,UIKit也或许会替换键盘,它或许会代表开发人员为非文本方针显现类似键盘的输入视图。(这段看不懂不要紧,官方文档想描述一些代码的事情,后边看代码就理解了)。
Text views和Text fields发送给其托付的音讯顺序如下:
- 就在文本方针成为榜首呼应者之前- textFieldShouldBeginEditing:(Text field)和textViewShouldBeginEditing:(Text view)。
Delegate能够经过回来YES(默许值)或NO来决议文本方针是否应该成为榜首呼应者。
- 就在文本方针成为榜首呼应者后- textFieldDidBeginEditing:(Text field)和textViewDidBeginEditing:(Text view)。
Delegate能够经过更新状况信息或(例如)在修改会话期间显现掩盖视图来呼应此音讯。
- 在修改阶段——各式各样。
当用户输入和修改文本时,text方针会调用某些托付办法(假如完成了)。例如,当任何文本发生改变时,Text view的Delegate能够接纳textViewDidChange:音讯。当用户点击Text field的铲除按钮时,Text field的Delegate能够接纳textFieldShouldClear:音讯;Delegate回来一个布尔值,指示是否应该铲除文本。
- 就在文本方针刊出榜首呼应者(resigns first responder)之前- textFieldShouldEndEditing:(Text field)和textViewShouldEndEditing:(Text view)。
Delegate完成这些办法的首要原因是验证输入的文本。例如,假如文本应该符合给定的格局,则Delegate在这儿验证输入的字符串,假如字符串不符合,则回来NO。默许回来值是YES。关于Text fields的一个相关办法是textFieldShouldReturn:。当用户点击回来键时,Text field类发送一个textFieldShouldReturn:音讯给Delegate,问询它是否应该刊出榜首个呼应者。
- 就在文本方针刊出榜首呼应值后,textFieldDidEndEditing:(Text field)和textViewDidEndEditing:(Text view)。
Delegate能够完成这些办法来获取用户刚刚输入或修改的文本。
Delegate以外的方针能够经过调查告诉来获取Text views和Text fields的榜首呼应者状况的改变。(但是,他们不能同意或拒绝向新状况的过渡。) 这些告诉有:比方UITextFieldTextDidBeginEditingNotification, UITextViewTextDidEndEditingNotification,和UITextViewTextDidChangeNotification。与textFieldDidEndEditing:和textViewDidEndEditing:相同,调查和处理UITextFieldTextDidEndEditingNotification和UITextViewTextDidEndEditingNotification告诉的首要意图是拜访相关Text field或Text view中的文本。请参阅UITextField Class Reference和UITextView Class Reference以了解有关这些类发出的告诉的更多信息。
装备Text fields和Text views
与UIKit框架供给的任何视图方针相同,你通常需要在Text fields和Text views显现之前装备它们。你能够经过编程办法装备它们,也能够运用Interface Builder的特点检查器。不管哪种情况,都是在设置特点。
一些特点是Text views和Text fields的一起特点,而其他特点则是特定于每种类型的方针,包括以下内容:
- 文本特征——文本颜色、对齐办法、Font族、FontTypeface和Font大小。
- keyboard——键盘类型、回来键名、安全文本输入项和auto-enabled回来键,所有这些都由UITextInputTraits协议声明。(请注意,与Text view相关的auto-enabled回来键在点击时充任回车键。)有关更多信息,请拜见装备文本方针的键盘。
- 特定于Text field的边框、背景图画、禁用图画、铲除按钮和占位符文本。作为UIControl方针,Text fields也具有高亮、选中、启用和其他特点。
- Text view特定-可修改状况,数据检测器(用于电话号码和URL链接)。因为Text view承继自UIScrollView,所以您还能够经过设置适当的特点来办理翻滚视图行为。
盯梢多个Text fields或Text views
文章原文想阐明,假如一个方针是多个Text view或Text filed的署理,那么怎么在署理办法里面区别是哪个Text object发送的音讯呢?能够经过指针相等,或许tag相等判断
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
if (textField == SSN) {
return NO;
}
return YES;
}
enum {
NameFieldTag = 0,
EmailFieldTag,
DOBFieldTag,
SSNFieldTag
};
- (void)textFieldDidEndEditing:(UITextField *)textField {
switch (textField.tag) {
case NameFieldTag:
// do something with this text field
break;
case EmailFieldTag:
// do something with this text field
break;
// remainder of switch statement....
}
}
获取输入的文本和设置文本
当用户在Text field或Text view中输入或修改文本而且修改会话结束后,Delegate应该获取文本并将其存储在应用程序的数据模型中。拜访输入文本的最佳托付办法是textFieldDidEndEditing:(Text fields)和textViewDidEndEditing:(Text views)。
清单3-3演示了如何获取用户在Text field中输入的文本(运用符号区别视图中的多个Text fields)。UITextField或UITextView的text特点保存了当时由text方针显现的字符串。Delegate从此特点获取字符串,并运用为每个字段定义的键将其存储在字典方针中。假如Text field没有字符串值(也就是说,该字段包括一个空字符串),Delegate将简单地回来。
清单3-3获取输入到Text field中的文本
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ([textField. text isEqualToString:@""])
return;
switch (textField.tag) {
case NameFieldTag:
[thePerson setObject:textField. text forKey:MyAppPersonNameKey];
break;
case EmailFieldTag:
[thePerson setObject:textField. text forKey:MyAppPersonEmailKey];
break;
case SSNFieldTag:
[thePerson setObject:textField. text forKey:MyAppPersonSSNKey];
break;
default:
break;
}
}
清单3-4显现了textViewDidEndEditing:办法的完成,该办法从Text view中获取显现的字符串并将其存储在字典中。这儿这个办法没有要求Text view抛弃firstresponder。(resignFirstResponder办法是在用户点击视图用户界面中的Done按钮时调用的操作办法中调用的。)
Listing 3-4 Getting the text entered into a text view
- (void)textViewDidEndEditing:(UITextView *)textView {
NSString *theText = textView.text;
if (![theText isEqualToString:@""]) {
[thePerson setObject:theText forKey:MyAppPersonNotesKey];
}
doneButton.enabled = NO;
}
假如需要将字符串写入文本方针(通常是从应用程序的数据模型中取得字符串后),只需将字符串赋值给文本方针的text特点即可。例如:
NSString *storedValue =[个人objectForKey:MyAppPersonEmailKey];
emailField.text = storedValue;
对Text fields运用格局化
Formatter方针自动解析特定格局的字符串,并将字符串转换为表明数字、日期或其他值的方针;它们也能够反过来作业,将NSDate、NSNumber等类似方针转换为表明这些方针值的格局化字符串。Foundation框架供给了笼统基类NSFormatter以及该类的两个具体子类NSDateFormatter和NSNumberFormatter。运用这些类,用户能够在Text field中输入如下值:
11/15/2010
-1348 .09
你的应用程序能够运用formatter方针将字符串别离转换为NSDate方针和NSNumber方针。
下面的代码清单运用一个date-formatter方针来阐明格局化器的用法。(当然,您能够运用UIDatePicker方针而不是Text field进行日期输入,但是带附加日期格局化程序的Text field是另一种挑选。)清单3-5中的代码创立了一个NSDateFormatter方针,并将其赋值给一个实例变量。它将日期格局化程序装备为对日期运用“短款式”,但以一种能够呼应日历、地区和时区改变的办法。它还以指定格局将今日的日期指定为占位符字符串,这样用户在输入日期时就有了一个模型。
Listing 3-5Configuring a date formatter
- (void)viewDidLoad {
[super viewDidLoad];
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setGeneratesCalendarDates:YES];
[dateFormatter setLocale:[NSLocale currentLocale]];
[dateFormatter setCalendar:[NSCalendar autoupdatingCurrentCalendar]];
[dateFormatter setTimeZone:[NSTimeZone defaultTimeZone]];
[dateFormatter setDateStyle:NSDateFormatterShortStyle]; // example: 4/13/10
DOB.placeholder = [NSString stringWithFormat:@"Example: %@", [dateFormatter stringFromDate:[NSDate date]]];
// code continues....
}
在装备了日期格局化器之后,Delegate能够调用格局化器上的dateFromString:办法将输入的日期字符串转换为NSDate方针,如清单3-6所示。
Listing 3-6Using anNSDateFormatter
object to convert a date string to a date object
- (void)textFieldDidEndEditing:(UITextField *)textField {
[textField resignFirstResponder];
if ([textField.text isEqualToString:@""])
return;
switch (textField.tag) {
case DOBField:
NSDate *theDate = [dateFormatter dateFromString:textField.text];;
if (theDate)
[inputData setObject:theDate forKey:MyAppPersonDOBKey];
break;
// more switch case code here...
default:
break;
}
}
有关NSDateFormatter和NSNumberFormatter的更多信息, seeData Formatting Guide.
验证输入的文本
字符串或许有必要是某种格局,或许值(在转换为数值之后)有必要在某个范围内。假如不先验证值,应用程序有时无法接受Text fields和Text views中输入的字符串。验证输入字符串的最佳托付办法是textFieldShouldEndEditing:(用于Text fields)和textViewShouldEndEditing:(用于Text views)。这些办法将在Text field或Text view抛弃榜首呼应者状况之前调用。回来NO文本方针仍然是修改的焦点。这是还应该显现一个正告框,告诉用户有过错。
清单3-7运用一个正则表达式来验证在“Social Security Number”字段中输入的字符串符合该数字的格局。
Listing 3-7Validating the format of a text field’s string using a regular expression
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
if (textField == SSN) { // SSN is an outlet
NSString *regEx = @"[0-9]{3}-[0-9]{2}-[0-9]{4}";
NSRange r = [textField. text rangeOfString:regEx options:NSRegularExpressionSearch];
if (r.location == NSNotFound) {
UIAlertView *av = [[[UIAlertView alloc] initWithTitle:@"Entry Error"
message:@"Enter social security number in 'NNN-NN-NNNN' format"
delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
[av show];
return NO;
}
}
return YES;
}
清单3-8中的textViewShouldEndEditing:完成对Text view中输入的文本实施Character限制。
Listing 3-8Validating a text view’s string for allowable length
- (BOOL)textViewShouldEndEditing:(UITextView *)textView {
if (textView.text.length > 50) {
UIAlertView *av = [[[UIAlertView alloc] initWithTitle:@"Entry Error"
message:@"You must enter less than 50 characters." delegate:self cancelButtonTitle:@"OK"
otherButtonTitles:@"Clear", nil] autorelease];
[av show];
return NO;
}
return YES;
}
经过完成textField:shouldChangeCharactersInRange:replacementString:办法,Delegate还能够在输入Text field时验证每个Character。清单3-9中的代码验证每个输入的Character(字符)是否表明一个数字。(你能够经过为Text field指定一个UIKeyboardTypeNumberPad键盘来完成同样的方针。)
Listing 3-9Validating each character as it’s entered
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
if ([string isEqualToString:@""]) return YES;
if (textField. tag == SalaryFieldTag) {
unichar c = [string characterAtIndex:0];
if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:c]) {
return YES;
} else {
return NO;
}
}
return YES;
}
还能够完成textField:shouldChangeCharactersInRange:replacementString:办法,在用户输入文本时供给或许的单词补全或更正功能。
在Text fields中运用叠加视图(Overlay Views)
叠加视图(Overlay Views)是刺进到Text field的左右角的小视图。当用户点击它们(通常是按钮)时,它们充任控件,并作用于Text field的当时内容。查找和添加书签是掩盖视图的两个常见任务
要完成掩盖视图,创立一个大小合适Text field高度的视图,并为该视图供给一个适当大小的图画。假如视图是按钮或其他控件,则指定方针方针、操作挑选器和触发的控件事情。通常你想要一个掩盖视图在它的Text field是修改的焦点时出现,所以在Delegate的textFieldDidBeginEditing:办法中将它分配给Text field的leftView或rightView特点。你能够经过给leftViewMode或rightViewMode特点赋一个UITextFieldViewMode常量来操控掩盖视图在修改会话期间何时出现——例如,在用户开端输入文本之前或之后。清单3-10展示了如何完成掩盖视图。
Listing 3-10Displaying an overlay view in a text field
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if (textField.tag == NameField && self.overlayButton) {
textField.leftView = self.overlayButton;
textField.leftViewMode = UITextFieldViewModeAlways;
}
}
@dynamic overlayButton;
- (UIButton *)overlayButton {
if (!overlayButton) {
overlayButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
UIImage *overlayImage = [UIImage imageNamed:@"bookmark.png"];
if (overlayImage) {
[overlayButton setImage:overlayImage forState:UIControlStateNormal];
[overlayButton addTarget:self action:@selector(bookmarkTapped:)
forControlEvents:UIControlEventTouchUpInside];
}
}
return overlayButton;
}
要删去掩盖视图,只需在textFieldDidEndEditing: delegation办法中把leftView或rightView特点设置为nil,如代码清单3-11所示。
Listing 3-11 Removing the overlay view
- (void)textFieldDidEndEditing:(UITextField *)textField {
if (textField.tag == NameFieldTag) {
textField.leftView = nil;
}
// remainder of implementation....
}
盯梢Text views中的挑选
UITextViewDelegate的textViewDidChangeSelection:办法让你盯梢用户在Text view中所做挑选的改变。你能够完成这个办法来获取选中的子字符串并对其进行一些操作。清单3-12是一个古怪的例子,它使所选子字符串中的所有Characters都大写。
Listing 3-12Getting the selected substring and changing it
- (void)textViewDidChangeSelection:(UITextView *)textView {
NSRange r = textView.selectedRange;
if (r.length == 0) {
return;
}
NSString *selText = [textView.text substringWithRange:r];
NSString *upString = [selText uppercaseString];
NSString *newString = [textView.text stringByReplacingCharactersInRange:r withString:upString];
textView.text = newString;
}