UITableViewCell 内的 UITextField - 防止文本重置的方法

Posted

技术标签:

【中文标题】UITableViewCell 内的 UITextField - 防止文本重置的方法【英文标题】:UITextField inside UITableViewCell - method for preventing text reset 【发布时间】:2013-08-30 14:43:07 【问题描述】:

我有一个足够高的UITableView,需要滚动。表格中最顶部的单元格包含一个UITextField,供用户输入一些文本。

构建它的标准方法可能是创建和添加文本字段并将其添加到在cellFOrRowAtIndexPath: 中创建或回收的单元格中。但是,这种不断的重新创建意味着在字段中输入的文本在单元格被滚动出来并返回到视图中。

到目前为止,我发现的解决方案建议使用UITextField 委托来跟踪文本的变化并将其存储在 iVar 或属性中。我想知道为什么推荐使用这种方法而不是我使用的更简单的方法:

我在UITableViewController 的init 方法中创建UITextField 并立即将其存储在一个属性中。在cellFOrROwAtIndexPath 我只是添加预先存在的字段而不是初始化一个新字段。单元格本身可以毫无问题地回收,但因为我一直使用唯一的UITextField,所以内容得以保留。

这是一个合理的方法吗?可能会出什么问题?任何改进(也许我仍然可以在cellForRowAtIndexPath 中创建该字段,但首先检查该属性是否为零?)

【问题讨论】:

【参考方案1】:

当您在 cellForRowAtIndexPath 中创建单元格时,您必须为第一个单元格(即 cellId1)使用一个可重复使用的标识符,而为其余的(即 cellId2)使用另一个标识符。

如果您这样做,当您通过调用[tableView dequeueReusableCellWithIdentifier:@"cellId1"] 获取第一个元素的单元格时,您将始终获得相同的对象,并且不会被其他单元格重用。

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

    MyCell *cell = nil;

    // Only for first row
    if (indexPath.row == 0) 
        static NSString *cellId1 = @"cellId1";
        cell = [tableView dequeueReusableCellWithIdentifier:cellId1];

        if (cell == nil) 
            cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId1];
        
    
    else 
        static NSString *cellId2 = @"cellId2";
        cell = [tableView cellId2];

        if (cell == nil) 
            cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault cellId2];
        
    

    // do whatever

    return cell;

【讨论】:

谢谢,但这并不能解决嵌入在单元格中的文本字段。 您可以在创建时将第一个单元格存储为您的类属性之一,并随时访问其内容。重点是一旦创建就不会被重复使用,其内容也不会被删除。 你说的很对 - 这比使用 init 更好。此外,我可以将 textview 本身存储为属性而不是单元格。如果有的话,这会强化我的问题——因为如果我有很多文本标签,我仍然认为你的方法比使用委托更好。希望有人能解释为什么不这样做。【参考方案2】:

如果只有一个 UITextField,那么我同意与使用 UITextField 委托相比,您的方法会更好/相同(我认为)。

但是,让我们假设您想要“扩展”您的视图,以便现在有大约 7-8 个或更多的 TextField。然后,如果您继续使用您的方法,那么问题将是您将在内存中存储 7-8 个或更多 TextField 并维护它们。

在这种情况下,更好的方法是只创建屏幕上可见的文本字段数量。然后,您创建一个字典来维护文本字段中存在的内容(您可以通过 UITextFieldDelegate 方法获得)。这样,重复使用单元格时可以使用相同的文本字段。只有值会改变,并由字典中的值决定。

顺便说一句,在 cellForRowAtIndexPath 中进行最少的创建,因为在每次表格滚动期间都会调用它,因此在 cellForRowAtIndexPath 中创建 textField 可能会很昂贵。

【讨论】:

【参考方案3】:
#import "ViewController.h"
#import "TxtFieldCell.h"

#define NUMBER_OF_ROWS 26

@interface ViewController ()<UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tablView;
@end

@implementation ViewController

- (void)viewDidLoad 
    [super viewDidLoad];
    self.tablView.datasource = self; //set textfield delegate in storyboard
    textFieldValuesArray = [[NSMutableArray alloc] init];
    for(int i=0; i<NUMBER_OF_ROWS; i++)
        [textFieldValuesArray addObject:@""];
    


- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];


#pragma mark - TableView Datasource

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    TxtFieldCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TxtFieldCellId" forIndexPath:indexPath];
    cell.txtField.tag = indexPath.row;
    if (textFieldValuesArray.count > 0) 
        NSString *strText = [textFieldValuesArray objectAtIndex:indexPath.row];

        cell.txtField.text = strText;
    
    return cell;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    return NUMBER_OF_ROWS;


#pragma mark - TextField Delegate

- (void)textFieldDidEndEditing:(UITextField *)textField 

   [textFieldValuesArray replaceObjectAtIndex:textField.tag withObject:textField.text];

【讨论】:

以上是关于UITableViewCell 内的 UITextField - 防止文本重置的方法的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 内的 UIView 上的 UIGestureRecognizer

UITableViewCell 内的 UIStackView

如何增加 UItableviewcell 内的 UItableview 高度?

捏放大到 UITableViewCell 内的 UIImageView

iOS - UITableViewCell 内的 UIScrollView 内的 UIView 未触发 UITapGestureRecognizer

UITableViewCell 内的 TableView - 必须注册一个 nib 或类