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

4
我有一个足够高的 UITableView,需要滚动才能显示。表格中最上面的单元格包含了一个 UITextField,供用户输入文本。
标准的创建方法可能是在 cellForRowAtIndexPath: 中创建并添加文本框,然后将其添加到一个已创建或回收的单元格中。然而,这种不断重新创建的方式导致当单元格被滚动出视图并再次进入视图时,文本框中输入的内容被抹掉。
我找到的解决方案建议使用 UITextField 的委托来跟踪文本的变化,并将其存储在 iVar 或属性中。我想知道为什么推荐这种方式,而不是我正在使用的更简单的方法:
我在 UITableViewController 的 init 方法中创建 UITextField 并立即将其存储在属性中。在 cellForRowAtIndexPath 中,我只需添加这个预先存在的文本框,而不是初始化一个新的文本框。单元格本身可以回收使用,但因为我总是使用唯一的 UITextField,所以内容得以保留。
这是一个合理的方法吗?可能会出现什么问题?是否有改进的余地(也许我仍然可以在 cellForRowAtIndexPath 中创建文本框,但首先检查属性是否为 nil)?
3个回答

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;
}

谢谢,但这并没有解决嵌入在单元格中的文本字段问题。 - Ben Packard
当创建时,您可以将第一个单元格存储为类属性之一,并在需要时访问其内容。关键是,一旦创建,它将不会被重用,其内容也不会被删除。 - clubifaximatic
你说得很对 - 这比使用init更好。此外,我可以将textview本身存储为属性,而不是单元格。不过,这也加强了我的问题 - 因为如果我有许多文本标签,我仍然认为你的方法比使用委托更好。希望有人能解释为什么不这样做。 - Ben Packard

0
如果只有一个UITextField,那么我同意你的方法会比使用UITextField委托更好/相同(我认为)。
然而,假设你想要“扩展”视图,使其现在有大约7-8个或更多的TextFields。如果你采用你的方法,那么问题就在于你将会存储7-8个或更多的TextFields并维护它们。
在这种情况下,更好的方法是:只创建屏幕上可见的文本字段数量。然后,创建一个字典来维护文本字段中的内容(可以通过UITextFieldDelegate方法获取)。这样,当单元格被重复使用时,可以使用相同的文本字段。仅值会改变,并由字典中的值指定。
另外,需要注意的是,在cellForRowAtIndexPath中进行最小限度的创建,因为在每次滚动表格时都会调用它,因此在cellForRowAtIndexPath中创建textField可能会很昂贵。

0
#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];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接