办理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发送给其托付的音讯顺序如下:

  1. 就在文本方针成为榜首呼应者之前- textFieldShouldBeginEditing:(Text field)和textViewShouldBeginEditing:(Text view)。

Delegate能够经过回来YES(默许值)或NO来决议文本方针是否应该成为榜首呼应者。

  1. 就在文本方针成为榜首呼应者后- textFieldDidBeginEditing:(Text field)和textViewDidBeginEditing:(Text view)。

Delegate能够经过更新状况信息或(例如)在修改会话期间显现掩盖视图来呼应此音讯。

  1. 在修改阶段——各式各样。

当用户输入和修改文本时,text方针会调用某些托付办法(假如完成了)。例如,当任何文本发生改变时,Text view的Delegate能够接纳textViewDidChange:音讯。当用户点击Text field的铲除按钮时,Text field的Delegate能够接纳textFieldShouldClear:音讯;Delegate回来一个布尔值,指示是否应该铲除文本。

  1. 就在文本方针刊出榜首呼应者(resigns first responder)之前- textFieldShouldEndEditing:(Text field)和textViewShouldEndEditing:(Text view)。

Delegate完成这些办法的首要原因是验证输入的文本。例如,假如文本应该符合给定的格局,则Delegate在这儿验证输入的字符串,假如字符串不符合,则回来NO。默许回来值是YES。关于Text fields的一个相关办法是textFieldShouldReturn:。当用户点击回来键时,Text field类发送一个textFieldShouldReturn:音讯给Delegate,问询它是否应该刊出榜首个呼应者。

  1. 就在文本方针刊出榜首呼应值后,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 anNSDateFormatterobject 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 Programming Guide for iOS - 04 - Managing Text Fields and Text Views

要完成掩盖视图,创立一个大小合适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;
}