iOS UITableView reloadData 导致键盘收起不能连续输入问题解决办法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS UITableView reloadData 导致键盘收起不能连续输入问题解决办法相关的知识,希望对你有一定的参考价值。
参考技术A 遇到的问题:产品设计了一个功能UITableViewCell中的一个UITextField的数字键盘,效果是每次输入数字后使执row的cell上面的数字跟输入的数字相乘,然后动态实时计算并展示出联动计算的结果。我在刷新整个表视图,这里使用了reloadData,会出现每输入一个数字就收回键盘不能连续输入的问题。
原因:
系统的reloadData和reloadRowsAtIndexPaths在执行的时候如果发现有的UITableView的子视图(例如这里的cell)有键盘已弹出正在响应(isFirstResponder),就会收起该键盘(resignFirstResponder)。
一种处理方法
方法一:我舍弃了reloadData方法,改用了指定行刷新的办法,让需要动态展示运算结果的cell 走reloadRowsAtIndexPaths单行刷新。这样就键盘就不会收起来了。可以连续输入。
方法二:也可以有键盘的cell自己来做控件显示更新,其他的cell刷新走reloadRowsAtIndexPaths。获取可见cell坐标数组(indexPathsForVisibleRows)剔除那个有键盘的IndexPath。
iOS开发之UITableView的使用
这一篇记录的是iOS开发中UITableView的使用,iOS中的UITableView跟Android中的ListView特别相似,以下用一个Demo来说明:
1、Xcode中新建projectTestSimpleTableViewproject
2、在Main.storyboard中拖入一个UITableView控件
3、在ViewController.h文件里,实现UITableViewDelegate和UITableViewDataSource协议
这里须要说下的是。为了给UITableView填充数据,须要让ViewController实现这两个协议,类似于Android中给ListView填充数据。须要为ListView指定一个Adapter,然后重写Adapter中的某些方法,iOS中也是一样的,实现了上面这两个协议后,须要实现这两个协议中的某些方法,才干为UITableView加入数据。
ViewController.h文件的代码例如以下:
#import <UIKit/UIKit.h> @interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> //界面中的UITableView控件 @property (weak, nonatomic) IBOutlet UITableView *tableView; //UITableView中的数据,用一个字符串数组来保存 @property (strong, nonatomic) NSMutableArray *tableDataArr; @end
为了将ViewController.h中声明的tableView变量,跟Main.storyboard中的UITableView控件联系起来,须要在Main.storyboard中做一些处理,例如以下图所看到的:
用鼠标右键点击Main.storyboard界面中的ViewController小圆钮,然后将Outlets中的tableView拖到面板中的UITableView控件上。这样就将变量和控件建立起联系了。
和Android中不同的是,要将变量和布局文件里的控件建立联系。我们是使用findViewById方法,通过控件的ID找到相应的控件。
4、以下须要在ViewController.m文件里,处理一些数据,首先须要在viewDidLoad方法里载入几条測试的数据。代码例如以下:- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //在这里载入一些数据。用于显示在UITableView上面 [self loadData]; } #pragma mark 载入一些数据,用于显示在UITableView上 - (void)loadData { //初始化数组 self.tableDataArr = [NSMutableArray array]; //加入20个字符串到数组中 for(int i = 0; i < 20; i++) { [self.tableDataArr addObject:[NSString stringWithFormat:@"table item %i", i]]; } }这里是直接用循环生成了20条TableView数据。
5、实现UITableViewDataSource中的两个方法:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 和
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
代码例如以下:
<span style="font-size:14px;">#pragma mark 该方法返回UITableView中的item个数 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.tableDataArr count]; } #pragma mark 该方法返回UITableView中每一个单元格,在这里处理每一个单元格中该显示什么数据 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //从队列中取出单元格 UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath]; //为单元格的label设置数据 cell.textLabel.text = [self.tableDataArr objectAtIndex:indexPath.row]; return cell; }</span>
这里的identifier是我们定义在方法外部的一个静态变量:
static NSString *identifier =@"TableViewCell";
这个变量的作用,就类似于Android中给一个ListItem设置tag,主要是为了重用TableViewCell而为单元格指定一个标识,通过这个标识就能找到单元格。6、到这里代码基本上就写完了,可是UITableView怎么知道该从哪里获取数据呢。在Android中为ListView指定数据,须要写一个适配器Adapter,然后调用ListView的setAdapter方法指定数据,在iOS中为UITableView指定数据,能够在Main.storyboard中,鼠标右键放到UITableView上面。然后拖拉到ViewController小圆钮上面,例如以下图所看到的:
除了使用上面的操作方式为UITableView指定数据源之外。还能够直接在代码中设置UITableView的数据源,能够在viewDidLoad方法中增加以下两行代码:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //在这里载入一些数据,用于显示在UITableView上面 [self loadData]; //不在Main.storyboard中设置数据源和托付的话,就用以下两行代码设置TableView的数据源和托付 self.tableView.delegate = self; self.tableView.dataSource = self; }7、假设这时候直接执行应用的话,会报错例如以下:
Terminating app due to uncaught exception ‘NSInternalInconsistencyException‘, reason: ‘unable to dequeue a cell with identifier TableViewCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard‘
原因是我们没有为UITableView指定单元格,还缺少以下一步:在Main.storyboard中拖一个TableViewCell控件到UITableView上面,例如以下图所看到的:
然后选中这个TableViewCell,在右側配置这个TableViewCell的标识,例如以下图所看到的:
注意这里填写的identifier要跟我们定义在代码中的那个identifier一致。这样才干正确载入UITableView,再次执行应用程序后。结果例如以下所看到的:
这里应该是有切割线的,可能在模拟器上显示不出来,所以在上图中没有显示出切割线。
8、给每一个单元格加上一个图片,这里能够通过以下的方法来给project加入一个图片:
然后在
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 方法中增加设置图片的代码例如以下所看到的:
#pragma mark 该方法返回UITableView中每一个单元格。在这里处理每一个单元格中该显示什么数据 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //从队列中取出单元格 UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath]; //为单元格的label设置数据 cell.textLabel.text = [self.tableDataArr objectAtIndex:indexPath.row]; //为单元格设置一个图片 cell.imageView.image = [UIImage imageNamed:@"icon.png"]; return cell; }这样就能够给单元格加上图片了,效果例如以下图所看到的:
9、假设想给单元格加上一个側滑删除的功能,须要实现协议中的一个方法:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
然后在这种方法中增加删除的代码例如以下:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { [self.tableDataArr removeObjectAtIndex:indexPath.row]; [self.tableView reloadData]; }增加上面的代码后就可以实现側滑删除的功能了。
以上是关于iOS UITableView reloadData 导致键盘收起不能连续输入问题解决办法的主要内容,如果未能解决你的问题,请参考以下文章