iOS SDk:创建一个自定义文本输入框

来源:互联网 发布:影视制作特效软件 编辑:程序博客网 时间:2024/05/17 06:47

创建一个好的应用不是一件简单的事,一般来说,最难做的是创建一个内容丰富,吸引人的界面。这个教程教你如何创建一个自定义的文本输入框。 

 

启动Xcode,创建一个Single View Application 

 

1.创建项目 

 

启动Xcode,创建一个Single View Application 

给项目命名,我的命名是CustomViewsDemo。 勾选Use Automatic Reference Counting。 

 最后,选择一个文件夹来保存这个项目,然后点击创建: 

 

 2.配置界面 

 

步骤1 

 

点击 ViewController.xib,打开Interface Builder。 首先反选Autolayout(这么做的原因是让这个demo可以在iOS 6之前的系统运行,Autolayout是iOS 6的功能): 

 

--如果Utilities面板看不到的话,找到Xcode工具栏,点击Utilities 按钮 。 

 

--点击File Inspector. 

 

--下拉框,找到Use Autolayout选项,反选。 

 

 步骤2

 

点击Attributes Inspector ,在Simulated Metrics标签下设置Size为None,这么做可以让项目可以在3.5寸的显示屏上运行。 

 步骤3 

 

添加一个UIToolbar到视图,将其放置在底部。 

 

 

--添加一个Flexible Space Bar Button item到默认的Bar Button Item左侧,让它留在工具栏左侧。 

 

--设置bar button item的名字。 

 

--设置button的颜色为:(R:51,G:51,B:51)。 

 

--设置工具栏toolbar的颜色为:(R:0,G:0,B:51)。 

 

步骤4 

 

下一步,添加一个 UITableView,放到剩下的空间里。设置Style样式为Grouped,设置Separator为Single Line。 

 

同时选择背景颜色为:(R: 51, G: 51, B: 51)。现在你的界面看上去会是这个样子: 

 

 3.IBOutlet 属性以及 IBAction 用法 

 

到下一步之前,我们要先把UITableView链接到一个IBOutlet属性里,然后给工具栏的bar button item(即Add item按钮)创建一个IBaction方法。可以这么做,在Interface Builder 

 

中,点击Xcode工具栏上的编辑控件的中间的按钮来隐藏Assistant Editor。 

 

 

步骤1, 

 

按住Ctrl键右击Table View,然后点击New Referencing Outlet,把它拖拽到Assistant Editor里,这样做就插入了一个新的IBOutlet属性。 

 

下一步给这个新属性命名,我给它命名为table。 

 

 步骤2 

 

按住Ctrl键右击 Bar Button item,点击Sent Action的Selector,把它拖拽到Assistant Editor,这么做就创建了一个IBAction。 

 

 

 给这个方法命名。我给他命名为addItem。 

 

 

 4. UItableView用法 

 

 步骤1 

 

为了使我们的table正确的工作,这一步我们需要调用一个minimum required table view方法。在这么做之前,首先我们需要设置table view 

 

点击 ViewController.h 文件,定义 @interface头文件 

 

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> 

 

进入了ViewController.m文件,在viewDidLoad下加入以下代码: 

 

// Set the tableview's delegate and datasource. 

 

[_table setDelegate:self];

 

[_table setDataSource:self]; 

 

步骤2 

 

一个NSMutableArray序列会成为我们列表项目的来源(表的内容)。首先,我们需要声明和初始化这个序列。进入 ViewController.m文件,找到最开始的部分,在 @interface 部分加上以下代码:

 

@interface ViewController () 

 @property (nonatomic, strong) NSMutableArray *sampleDataArray; 

 @end 

 

同时在viewDidload加上:

 

// Initialize the sample data array. 

 _sampleDataArray = [[NSMutableArray alloc] init]; 

 

步骤3: 

 

接入table view的methods。首先加上sections的编号

 

-(int)numberOfSectionsInTableView:(UITableView *)tableView{ 

 // Set the number of sections inside the tableview. We need only one section. 

 return 1; 

 }

然后设置序列的总数。总数和_sampleDataArray序列中的全部对象数相同

 

-(int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 

 // The number of rows is equal to the number of the sample data in our tableview. 

 return [_sampleDataArray count]; 

 

然后设置每列的高度:

 

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 

 // Set the row height. 

 return 45.0; 

 

 

现在,设置我们的view。在代码里面你可以找到所有view的定制信息。有详细注释。也可以根据你的想法进行定制:

 

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 

 static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    if (cell == nil) { 

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 

        // Let's set some custom cell options. 

        // Set the cell's background. 

        [cell setBackgroundColor:[UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0]]; 

        // Set the selection style. 

        [cell setSelectionStyle:UITableViewCellSelectionStyleGray]; 

        // Set the accessory type. 

        [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; 

        // Set a font for the cell's textlabel. 

        [[cell textLabel] setFont:[UIFont fontWithName:@"Georgia" size:15.0]]; 

    } 

    [[cell textLabel] setText:[_sampleDataArray objectAtIndex:[indexPath row]]]; 

    return cell; 

 

这部分暂时这样,过会儿再来。 

 

总结一下,至今我们现在已经创建了项目, 使用Interface Builder创建了界面。连接了必须的IBOutlet属性以及IBAction方法,接入了可以让我们的table基本顺利工作的方法。现在让我们去创建一个自定义的文本输入框。待会儿再继续使用ViewController 

 

5.Custom Text Input View Controller 

 

在开发的时候,保持所有代码整洁有序是非常好的习惯。所以,我们要为 text input view controller创建一个新的group。

 

步骤1

 

找到在Xcode左侧的Project Navigation面板,按住Ctrl键右击CustomViewsDemo group ,然后从弹出的目录中选择New Group 项。

 

 

 给这个New Group 命名为:Custom Text Input View 

 

 

 步骤2 

 

现在我们准备添加新的view controller。按住Ctrl键右击CustomViewsDemo group ,选择New File,

 

 

这个新文件的模板选择Objective-C class,点击Next下一步。

 

 

在Class框中输入CustomTextInputViewController ,选择 Subclass of框中的UIviewController,勾选With XIB for user interface选项 。 

 

 

最后,点击Create按钮。确保选中了Custom Text Input View ,如下图所示:

 

6. Text Input View's Interface文本输入框界面 

 

步骤1 

 

点击 CustomTextInputViewController.xib 文件隐藏Interface Builder,创建界面。

 

--和先前做的一样,反选Autolayout 选项(Utilities面板>File Inspector>点击Use Autolayout checkbox 

 

--点击Attributes Inspector ,在Simulated Metrics下把Size选为None。 

 

步骤2

 

现在可以添加我们想要的subviews到我们的view里了。根据以下办法来增加subviews,同时选择他们的属性 

 

1. UILabel 

 

o Frame: X: 0.0, Y: 145.0, Width: 320.0, Height: 30 

 

o Font:: Georgia, 17.0 

 

o Color:: Black 

 

o Alignment:: Center 

 

o Background Color: (R: 204, G: 204, B: 204) 

 

2. UITextField 

 

o Frame: X: 0.0, Y: 180.0, Width: 320.0, Height: 30.0 

 

o Font: Georgia, 15.0 

 

o Color: Black 

 

o Border Style: Bezel 

 

o Clear button: Appears while editing 

 

o Capitalization:Sentences 

 

o Return Key: Done 

 

o Background Color: White 

 

大部分设置都会出现在下面的图像中。

 

 

3. UIToolBar 

 

o Frame: X: 0.0, Y: 225.0, Width: 320.0, Height: 44.0 

 

o Tint Color: (R: 204, G: 204, B: 204) 

 

注意Y坐标现在并不重要,因为根据每个subview的不同,他会自动调整。 

 

步骤3 

 

添加以下的UIBarButton项 到toolbar,紧邻默认的bar button按钮项 

 

" A flexible space bar button item 

 " Another bar button item 

 

同时选择这两个bar button items(不选flexible space item),设置他们的颜色为: (R: 51, G: 51, B: 51)。左边的bar button按钮命名为Okay。右边的bar button按钮命名为Cancel 

 

最后,选择所有的三个subviews(UILable,UITextField,以及UIToolBar),设置Autosizing的值如下所示( Flexible Width, Flexible Right Margin, Flexible Left Margin, and Flexible Bottom Margin

 

7. IBOutlets & IBActions

 

之前我向大家展示了如何创建IBOutlet属性以及IBAction方法,以及如何把他们和subviews链接起来。重复之前的步骤,创建并且分别连接属性到UILabel UITextField,, UIToolbar。 

 

@property (weak, nonatomic) IBOutlet UILabel *lblTitle; 

 @property (weak, nonatomic) IBOutlet UITextField *txtText; 

 @property (weak, nonatomic) IBOutlet UIToolbar *toolbarIAV;

 

然后声明并链接下一个IBAction到Okay和Cancel按钮。

 

- (IBAction)acceptTextChanges:(id)sender; 

 - (IBAction)cancelTextChanges:(id)sender; 

 

至此Interface Builder的工作就结束了。现在可以编码我们文本框的属性了。 

 

 

8. 编码 

 

步骤1 

 

首先我们要设置view controller为文本框的delegate。点击CustomTextInputViewController.h文件,修改 @interface头文件为: 

 

@interface CustomTextInputViewController : UIViewController 

 

然后, 到CustomTextInputViewController.m文件,在viewDidLoad中设置delegate。 

 

// Set the textfield delegate. 

[_txtText setDelegate:self]; 

 

同时到 viewDidLoad 设置UIToolbar作为文本框的 Input Accessory View 。 

 

// Set the textfield delegate.

[_txtText setDelegate:self];

// Set the input accessory view of the textfield.

[_txtText setInputAccessoryView:_toolbarIAV];

 

到目前为止,非常好。在本教程的开头,我提到了view controller的view会作为一个防护性的东西,目的是防止用户在我们的view之外输入内容。同时我们也要让view变成半透明的,这样看上去会比较好看。所以添加下面的代码来修饰我们的view。 

 

// Set the background color of the view to a semi-transparent gray. 

[self.view setBackgroundColor:[UIColor colorWithRed:0.66 

                                                  green:0.66 

                                                  blue:0.66 

                                                  alpha:0.75]]; 

 

现在来思考一下。之前说的,我们需要文本框在input accessory view(toolbar)正上方显现,同时标题标签出现在文本框上方。要做到这样,我们需要知道键盘框和input accessory view的起点,这样我们可以依次调整文本框和标签。但是我们怎么知道什么时候出现键盘,怎么得到它的大小以及起点呢? 

 

答案很简单,每次键盘快要出现的时候,iOS会发送一个通知,叫做UIKeyboardWillShowNotification(实际上,iOS会发送很多通知,但现在我们没必要管它们)。我们可以添加view controller来接收这个通知,当通知发送过来的时候会call一个预先定义的方法(这个我们来添加)。添加下面的代码,进入viewDidLoad方法。 

 

// Add self as observer to the NSNotificationCenter so we know when the keyboard is about to be shown up. 

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowWithNotification:) name:UIKeyboardWillShowNotification object:nil]; 

 

注意 keyboardWillShowWithNotification,这个我们待会儿要接入的。 

 

我们还要考虑一下status bar。我们的subviews的显现位置取决于status bar和它的高度。因此,如果我们有一个status bar(以它的高度)创造出来的偏移距离变量会非常好。 

 

到文件的头部,在@interface的private part声明一个CGFloat变量,这个变量会代表status bar的偏移距离。 

 

同时声明 keyboardWillShowWithNotification: 

 

@interface CustomTextInputViewController (){ 

    CGFloat statusBarOffset; 


-(void)keyboardWillShowWithNotification:(NSNotification *)notification; 

@end 

 

过会儿再来管status bar。 

 

步骤2 

 

现在我们要开始到接入阶段了。这样我们可以创建一个必须的public methods,这个方法可以被其他classes接入。 

 

每个方法要做什么必须很清楚。 

 

-(void)showCustomTextInputViewInView:(UIView *)targetView 

                            withText:(NSString *)text 

                            andWithTitle:(NSString *)title; 

-(void)closeTextInputView; 

-(NSString *)getText; 

 

首先是showCustomTextInputViewInView:withText:andWithTitle  method。开始编码之前,有几点必须提一下。首先,我们要检查status bar是否可见,设好statusBarOffset的value。我们可以轻易看出它是否可见,然后得到它的size。然而,如果status bar是可见的话,这儿有个小陷阱,我们需要处理portrait 和landscape方向。在portrait模式下,status bar的尺寸是宽*高的,而landscape模式下尺寸大小是高*宽的。对我们来说,最简单的确定status bar的高度是检查宽和高的最小值。使用这个方法我们一定可以得出正确的值来。把这个加到接下来的代码里。 

 

你可能还记得我们把Autolayout功能给关闭了,所以我们必须确保我们view的方向是正确的。 这就意味着我们每次调用这个方法的时候都必须检查一下方向,并且以此设定view的框架 

 

必须注意到在landscape模式下屏幕的宽度是view的高度,而屏幕的高度则是view的的高度。同时由于status bar是可见的,在landscape模式下,在view的左边会有一块边距,这个边距是需要消除的。 

 

这就是为什么之前我们需要声明 statusBarOffset。 

 

最后,我们希望的是最开始的时候view是不显现的,伴随着动画,它慢慢出现在屏幕上。 

 

现在来演示一下。打开CustomTextInputViewController.m,接入以下method; 

 

-(void)showCustomTextInputViewInView:(UIView *)targetView withText:(NSString *)text andWithTitle:(NSString *)title{ 

if (![[UIApplication sharedApplication] isStatusBarHidden]) { 

        CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size; 

        if (statusBarSize.width < statusBarSize.height) { 

            // If the width is smaller than the height then this is the value we need. 

            statusBarOffset = statusBarSize.width; 

        } 

        else{ 

            // Otherwise the height is the desired value we want to keep. 

            statusBarOffset = statusBarSize.height; 

        } 

    } 

    else{ 

        // Otherwise set it to 0.0. 

        statusBarOffset = 0.0; 

    } 

    // Before showing the self.view on-screen, we need to calculate the following 

    // values, depending always on the orientation. 

    CGFloat x, width, height; 

    if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || 

        [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight){ 

        // Landscape orientation. 

        // Set the x point for the view. If we don't substract the statusBarOffset value then a 

        // padding is going to exist at the left of the view when it will appear. 

        x = targetView.frame.origin.x - statusBarOffset; 

        // In landscape orientation, the width of the view equals to the height of the target view. 

        width = targetView.frame.size.height; 

        // The same with the height. 

        height = targetView.frame.size.width; 

    } 

    else{ 

        // In portrait orientation everything is normal. 

        x = targetView.frame.origin.x; 

        width = targetView.frame.size.width; 

        height = targetView.frame.size.height; 

    } 

    // Initially set the self.view off screen. That's why the y point equals to -height. 

    [self.view setFrame:CGRectMake(x, 

                                   -height, 

                                   width, 

                                   height)]; 

    // Add the view to the target view. 

    [targetView addSubview:self.view]; 

    // Begin animating the appearance of the view. 

    [UIView beginAnimations:@"" context:nil]; 

    [UIView setAnimationDuration:0.25]; 

    [UIView setAnimationCurve:UIViewAnimationCurveLinear]; 

    // We simply want the y point of the origin to become 0.0. 

    [self.view setFrame:CGRectMake(self.view.frame.origin.x, 

                                   0.0, 

                                   self.view.frame.size.width, 

                                   self.view.frame.size.height)]; 

    [UIView commitAnimations]; 

    // Set the textfield as the first responder to make the keyboard appear. 

    [_txtText becomeFirstResponder]; 

    // Set the text to edit (if exists) to the textfield. 

    [_txtText setText:text]; 

    // Set the label's text (the title above the textfield). 

    [_lblTitle setText:title]; 

 

代码的注释已经解释的很清楚了。注意在内部我们调用了 _txtText文本框的becomeFirstResponder 方法,这样做输入键盘也会显现。不久我们就可以看到这个调用有多么的重要,这是我们view在正确的位置出现的关键点。 

 

现在,让我们来接入下一个方法。view的关闭和他的显现方式是正好相反的。 

 

-(void)closeTextInputView{ 

    // Resign the textfield from first responder to make the keyboard go away. 

    [_txtText resignFirstResponder]; 

    // Animate the view closing. It's just the opposite from the showing animation. 

    [UIView beginAnimations:@"" context:nil]; 

    [UIView setAnimationDuration:0.25]; 

    [UIView setAnimationCurve:UIViewAnimationCurveLinear]; 

    [self.view setFrame:CGRectMake(self.view.frame.origin.x, 

                                   -self.view.frame.size.height, 

                                   self.view.frame.size.width, 

                                   self.view.frame.size.height)]; 

    [UIView commitAnimations]; 

    // Also remove the view from the superview after a while (we must let the animation finish first). 

    [self.view performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.25]; 

 

请注意,我们不是立刻把view从superview上移除的,而是等到动画结束以后。 

 

最后,是第三个方法。 

 

-(NSString *)getText{ 

// Return the textfield's text. 

    return [_txtText text]; 

 

步骤3 

 

这一步会向您展示如何处理输入键盘。在界面的private部分我们申明了下面这个方法: 

 

-(void)showCustomTextInputViewInView:(UIView *)targetView withText:(NSString *)text andWithTitle:(NSString *)title; 

 

 

每次输入键盘将要出现的时候这个method会被调用,同时UIKeyboardWillShowNotification会发送通知。通知参数包含了一个NSDictionary,这里面包含了关于输入键盘的信息。里面有键盘的大小以及出现的坐标。我们这儿需要的是坐标点,因为如果我们知道键盘出现的Y坐标,我们就可以合理的分配输入框和label。同样的,在landscape模式下键盘的x坐标和y坐标是正好相反的。 

 

以下是需要用到的代码: 

 

-(void)keyboardWillShowWithNotification:(NSNotification *)notification{ 

    // Get the userInfo dictionary from the notification object. 

    NSDictionary *info = [notification userInfo]; 

    // Get the keyboard origin. 

    CGPoint keyboardOrigin = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin; 

    CGFloat keyboardOriginY; 

    if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || 

        [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight){ 

        // In landscape orientation the x point represents the vertical axis. 

        keyboardOriginY = keyboardOrigin.x; 

    } 

    else{ 

        keyboardOriginY = keyboardOrigin.y; 

    } 

    // Set the appropriate frame for the textfield. That is just right above the input accessory view. 

    [_txtText setFrame:CGRectMake(_txtText.frame.origin.x, 

                                  keyboardOriginY - _txtText.frame.size.height - statusBarOffset, 

                                  _txtText.frame.size.width, 

                                  _txtText.frame.size.height)]; 

    // Set the label's frame in turn. 

    [_lblTitle setFrame:CGRectMake(0.0, 

                                   _txtText.frame.origin.y - _lblTitle.frame.size.height, 

                                   _lblTitle.frame.size.width, 

                                   _lblTitle.frame.size.height)]; 

 

我相信你肯定注意到了statusBarOffset的subtraction。如果我们不这样做的话,文本框会被input accessory view给遮挡住。 

 

步骤4 

 

我们现在需要定义协议了。到这一步, view controller现在基本准备完毕,但是还差最后一点工作。现在缺的是定义协议,这个协议可以让使用的delegate class(在我们的例子里是viewcontroller)接入可以处理Okay和Cancel按钮的必要方法。 

 

找到CustomTextInputViewController.h文件,然后定义一个协议,附上下面的delegate方法: 

 

@protocol CustomTextInputViewControllerDelegate

-(void)shouldAcceptTextChanges;

-(void)shouldDismissTextChanges;

@end

 

同时,在@interface头文件后,加上下面的代码: 

 

@interface CustomTextInputViewController : UIViewController

@property (nonatomic, strong) id delegate;

...

...

 

这么做了以后,delegate class就应该和shouldAcceptTextChanges method链接好了,可以处理触碰okay按钮,shouldDismissTextChanges method也链接好了,可以处理触碰Cancel按钮。 

 

但是,这个class里的IBAction 方法有什么作用呢?现在这一片是没有用上的。让我们输入以下代码: 

 

- (IBAction)acceptTextChanges:(id)sender { 

[self.delegate shouldAcceptTextChanges]; 


- (IBAction)cancelTextChanges:(id)sender { 

    [self.delegate shouldDismissTextChanges]; 

 

触碰okay按钮的时候shouldAcceptTextChanges的delegate method会被调用,触碰cancel按钮的时候shouldDismissTextChanges的delegate方法会被调用。 

 

但是为了完全正确,还有一步要做:要让键盘的Done 按钮可以使用。这么做,我们必须接入 -(BOOL)textFieldShouldReturn的delegate method。 

 

-(BOOL)textFieldShouldReturn:(UITextField *)textField{ 

// The tap on the Done button of the keyboard equals to the Okay button. 

    [self.delegate shouldAcceptTextChanges]; 

    return YES; 

 

现在我们新的自定义view就准备好了。 

 

9.文本输入框投入使用 

 

步骤1 

 

在我们见证新的自定义文本输入框工作之前,还有几步工作需要做。首先,我们必须声明ViewController class作为它的 delegate委托类。打开ViewController.h文件,导入 CustomTextInputViewController.h 文件,让我们的class的delegate在interface头文件调用。 

 

#import <UIKit/UIKit.h> 

#import "CustomTextInputViewController.h" 

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, CustomTextInputViewControllerDelegate> 

@property (weak, nonatomic) IBOutlet UITableView *table; 

... 

... 

 

现在找到ViewController.m文件,在@interface的private part声明一个CustomTextInputViewController对象。我把它命名为 textInput。 

 

@interface ViewController () 

@property (nonatomic, strong) NSMutableArray *sampleDataArray; 

@property (nonatomic, strong) CustomTextInputViewController *textInput; 

@end 

 

初始化viewDidLoad方法: 

 

// Initialize the custom text input object. 

_textInput = [[CustomTextInputViewController alloc] init]; 

[_textInput setDelegate:self]; 

 

步骤2 

 

调用addItem IBAction method让我们的文本输入框显现: 

 

- (IBAction)addItem:(id)sender { 

[_textInput showCustomTextInputViewInView:self.view 

                                    withText:@"" 

                                    andWithTitle:@"Add new item"]; 


很简单,不是吗? 

 

如果我们现在运行应用,你就会看到文本输入框已经可以使用了,但是okay和cancel按钮还不行,这是因为我们还没有接入delegate方法。加上以下代码: 

 

-(void)shouldAcceptTextChanges{ 

    // Add the new item to the sampleDataArray. 

    [_sampleDataArray addObject:[_textInput getText]]; 

    // Reload the table using animation. 

    [_table reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic]; 

    // Close the text input. 

    [_textInput closeTextInputView]; 


-(void)shouldDismissTextChanges{ 

    [_textInput closeTextInputView]; 

 

运行,现在这两个按钮就可以工作了。你可以任意输入文字,但是还没有完成,我们还不能编辑任何items。 

 

步骤3 

 

现在我们需要访问table view的delegate方法了, -(void)tableView:didSelectRowAtIndexPath。我们想要我们输入的文字都能进行编辑。于是我们还需要知道用户什么时候增加或者编辑文字。所以我们必须使用一个flag来判断表明我们的用户是否要编辑文字。 

 

找到@interface的private part,加入以下变量: 

 

@interface ViewController (){

BOOL isEditingItem;

}

@property (nonatomic, strong) NSMutableArray *sampleDataArray;

@property (nonatomic, strong) CustomTextInputViewController *textInput;

@end

 

  

不要忘记加上大括号。进入 viewDidLoad设置value值为NO。 

 

// Set the initial value of the isEditingItem flag. 

isEditingItem = NO; 


现在到table的 delegate method: 

 

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 

    [_textInput showCustomTextInputViewInView:self.view 

                                    withText:[_sampleDataArray objectAtIndex:[indexPath row]] 

                                    andWithTitle:@"Edit item"]; 

    // Set the isEditingItem flag value to YES, indicating that 

    // we are editing an item. 

    isEditingItem = YES; 

 

到了这个阶段,当你触碰在文本框中的文字时,文本输入框就会出现,可以对文字进行编辑了。但是无论你怎么努力,你编辑的都无法保存替代掉旧的文本,而会以新的文本形式存储起来。这就说明我们还需要做一些小调整,修改 -(void)shouldAcceptTextChanges 的delegate method如下; 

 

-(void)shouldAcceptTextChanges{

    // If the isEditingItem flag is set to NO, then a new item has been

    // added to the list. Otherwise an existing item has been edited.

    if (!isEditingItem) {

        // Add the new item to the sampleDataArray.

        [_sampleDataArray addObject:[_textInput getText]];

    }

    else{

        // Replace the selected item into the array with the updated value.

        NSUInteger index = [[_table indexPathForSelectedRow] row];

        [_sampleDataArray replaceObjectAtIndex:index withObject:[_textInput getText]];

        // Set the isEditingItem flag to NO.

        isEditingItem = NO;

    }

    // Reload the table using animation.

    [_table reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];

    // Close the text input.

    [_textInput closeTextInputView];

}

 

记得当修改文本内容的时候,在相同的数据序列中的同等对象会被替换。同时,还要注意isEditingItem,它取得是NO值。 

 

现在,所有问题都解决了。运行然后在portrait模式和landscape模式下都测试下吧。 

 


原创粉丝点击