保存单元格中的UITextField文本到NSUserDefaults



我看了每一个接近这个问题的帖子,仍然没有找到有用的东西。我在每个单元格中都有textFields,用作用户填写的表单。单元格的一切都很好,除了当滚动时,当单元格滚动出屏幕时,textFields中的输入就消失了。我知道这是因为dequeue。但是应该有一种方法来保存输入的数据,这样它就不会在滚动或退出应用程序时消失。我还希望能够将这些信息作为PDF或文档通过电子邮件发送。实现这一目标的最佳方式是什么?下面的代码是我如何生成单元格等的示例。

. h文件
@interface MasterViewController : UITableViewController <UITextFieldDelegate, UITextFieldDelegate, UITableViewDataSource, UINavigationBarDelegate>{
    NSString* name_;
    UITextField* nameFieldTextField;
}
// Creates a textfield with the specified text and placeholder text
-(UITextField*) makeTextField: (NSString*)text
              placeholder: (NSString*)placeholder;
// Handles UIControlEventEditingDidEndOnExit
- (IBAction)textFieldFinished:(id)sender;
@property (nonatomic,copy) NSString* name;

。m文件

@synthesize name = name_;
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
self.name = @"";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    // Make cell unselectable and set font.
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont fontWithName:@"ArialMT" size:13];
    if (indexPath.section == 0) {
    UITextField* tf = nil;
    switch ( indexPath.row ) {
        case 0: {
            cell.textLabel.text = @"Name" ;
            tf = nameFieldTextField = [self makeTextField:self.name placeholder:@"John Appleseed"];
            nameFieldTextField.tag = 1;
            [cell addSubview:nameFieldTextField];
            break ;
    }
    // Textfield dimensions
    tf.frame = CGRectMake(120, 12, 170, 30);
    // Workaround to dismiss keyboard when Done/Return is tapped
    [tf addTarget:self action:@selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit];
 }
 return cell;
}

// Textfield value changed, store the new value.
- (void)textFieldDidEndEditing:(UITextField *)textField {
        //Section 1.
    if ( textField == nameFieldTextField ) {
    self.name = textField.text ;
}
}
- (void)viewWillAppear:(BOOL)animated{
    NSString *nameCellString = [[NSUserDefaults standardUserDefaults] stringForKey:@"nameCellString"];
nameFieldTextField.text = nameCellString;
}
- (void)viewWillDisappear:(BOOL)animated{
    NSString *nameCellString = self.name;
    [[NSUserDefaults standardUserDefaults] setObject:nameCellString forKey:@"nameCellString"];
}

这里实际上有两个问题,它们都是在您的cellForRowAtIndexPath:实现中。

  • 您正在将文本字段放入单元格中,即使此单元格被重用并且已经具有文本字段。因此,您实际上是在文本字段上堆叠文本字段,覆盖了先前存在的文本字段。

  • 如果该行(索引路径)的文本字段中已经有文本,则不将文本放回文本字段。

换句话说,单元格是(正如您正确地说的)重用的,因此您需要考虑这一事实。您必须查看传入单元格的状态,并相应地重新配置单元格。

首先,我建议您考虑在故事板中创建一个自定义单元格,并抓住它。这比编程简单多了,我认为这是未来的趋势。也就是说,考虑用nsarray填充你的tableview,而不是硬编码字符串到cellForRowAtIndexPath方法。我冒昧地给你们举个例子。

以下是基于您的代码,应该是复制/粘贴解决方案。仔细检查一下,看看它是如何操作的。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *titlesArray = @[@"Name", @"Birthday", @"Favorite Food"];
    UITableViewCell *cell;
    cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@"%i%i", indexPath.section, indexPath.row]];
    if (cell == nil) {
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    // Make cell unselectable and set font.
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont fontWithName:@"ArialMT" size:13];
    // Populate label from array
    cell.textLabel.text = titlesArray[indexPath.row];
    if (indexPath.section == 0) {
    UITextField* tf = nil;
    switch ( indexPath.row ) {
        case 0: {
            tf = nameFieldTextField = [self makeTextField:self.name placeholder:@"John Appleseed"];
            nameFieldTextField.tag = 1;
            [cell addSubview:nameFieldTextField];
            break ;
    }
    // Textfield dimensions
    tf.frame = CGRectMake(120, 12, 170, 30);
    // Workaround to dismiss keyboard when Done/Return is tapped
    [tf addTarget:self action:@selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit];
 }
    // Set the reuse identifier to a unique string, based on placement in table
    // This ensures that the textField will retain its text
    cell.reuseIdentifier = [NSString stringWithFormat:@"%i%i", indexPath.section, indexPath.row];
}
 return cell;
}

// Textfield value changed, store the new value.
- (void)textFieldDidEndEditing:(UITextField *)textField {
        //Section 1.
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    switch (textField.tag) {
        case 1:
            [defaults setObject:textField.text forKey:@"nameCellString"];
            self.name = textField.text;
            break;
        default:
            break;
    }
    [defaults synchronize];
}

编辑:更改为容纳更多单元格

你应该为你的tableDataSourceArray使用UIDictionary数组,就像:

step1) 
NSArray *tableDataSourceArray = [[NSArray alloc]init];
NSMutableDictionary *cellData = [[NSMutableDictionary alloc]init];
[cellData setValue:@"" forKey:@"Name"];
...//so on
[tableDataSourceArray addObject:cellData];
cellData = nil;
repeat step1 as number of records you have.

现在在cellForRowAtIndexPath:

 nameFieldTextField.tag = indexPath.row; //To store index of dataSourceArray
    nameFieldTextField.text = [[tableDataSourceArray objectAtIndex:indexPath.row] valueForKey:@"Name"];

最后在textFieldDidEndEditing:

NSMutableDictionary *cellDataDic = tableDataSourceArray objectAtIndex:textField.tag];

[cellDataDic setValue:文本框。文本forKey: @"名字");

希望对你有帮助。

我认为解决问题的最简单方法是为您的单元格创建一个新类(从UITableViewCell继承)并添加新属性,如customerTextField (UITextField)。在构造函数中添加新的文本字段,但使用CGRectZero。在layoutSubviews方法中,您将为文本字段分配CGRect。一般来说,这种方法将使您的UIViewController更干净(您将减少对文本字段状态的检查次数)。

最新更新