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

Posted

技术标签:

【中文标题】将单元格中的 UITextField 文本保存到 NSUserDefaults 中?【英文标题】:Saving UITextField text in cell into NSUserDefaults? 【发布时间】:2013-05-21 00:18:32 【问题描述】:

我看过每一篇与这个问题很接近的帖子,但仍然没有找到有用的东西。我在每个单元格中都有文本字段,用作用户填写的表单。除了滚动时,单元格的所有内容都可以正常工作,当单元格滚动离开屏幕时,textFields 中的输入会消失。我知道这是因为出队。但是应该有一种方法可以保存输入的数据,以便在滚动或退出应用程序时它不会消失。我还希望能够获取此信息并将其作为 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"];


【问题讨论】:

我在您之前的问题中添加了answer,并附有源代码。看看这个。我认为它会涵盖这两个问题。 【参考方案1】:

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

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

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

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

【讨论】:

好的,我还是个编程新手,你能提供一个例子,说明我将如何根据上面的代码做到这一点吗?【参考方案2】:

首先,我敦促您考虑在情节提要中创建一个自定义单元格,然后抓住它。这比编码要容易得多,我认为这是未来。也就是说,请考虑使用 NSArrays 填充您的 tableViews,而不是将字符串硬编码到 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];

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

【讨论】:

会有很多单元格,你还想什么其他方法? 如果使用更多单元格,请查看编辑。注意:在您的dequeueReusableCellWithIdentifier: 中包含forIndexpath:indexpath 将导致此功能无效。我不知道为什么。【参考方案3】:

您应该为您的 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:textField.text forKey:@"Name"];

希望对你有所帮助。

【讨论】:

【参考方案4】:

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

【讨论】:

以上是关于将单元格中的 UITextField 文本保存到 NSUserDefaults 中?的主要内容,如果未能解决你的问题,请参考以下文章

自定义表格视图单元格中的 UITextField。点击单元格/文本字段时显示选择器视图

滚动 UITableView 时自定义单元格中的 UITextField 文本正在更改

向单元格中的 uitextfield 添加方法?

在表格单元格中获取/设置 UITextField 值

iOS:如何从 tableview 的自定义单元格中的 UITextField 访问值

将文本字段数据保存在 xcode 中的可扩展表格单元格中