使用 UIButton 清除 UITableView 中的所有 UITextField 更改

发布于 2024-10-27 19:15:33 字数 709 浏览 2 评论 0原文

我有一个包含十几行的 UITableView,每行包含一个 UITextField。 默认情况下,如果用户之前没有编辑过文本字段,则 UITextField 包含一个占位符值“添加值”:

UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(158, 6, 148, 24)];

NSString *strReplacement = [valueArray objectAtIndex:indexPath.row];

if (([strReplacement length] != 0) {
    textField.text = strReplacement;
} else {
    textField.placeholder = @"Add Value";
}

textField.delegate = self;
[cell addSubview:textField];
[textField release];

到目前为止一切顺利。

我还在 UITableView 的页脚中添加了一个 UIButton。 我想要的是当用户单击 UIButton 时清除所有编辑的值并刷新 UITableView 中的所有 UITextField。

我可以轻松地从 valueArray 中删除所有对象,但我不知道如何刷新所有 UITableView 单元格以反映更改。

任何帮助表示赞赏。 lq

I have a UITableView with a dozen rows, each containing a UITextField.
By default the UITextField contains a placeholder value "Add Value" if the user hasn't previously edited the text field:

UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(158, 6, 148, 24)];

NSString *strReplacement = [valueArray objectAtIndex:indexPath.row];

if (([strReplacement length] != 0) {
    textField.text = strReplacement;
} else {
    textField.placeholder = @"Add Value";
}

textField.delegate = self;
[cell addSubview:textField];
[textField release];

So far so good.

I've also added a UIButton to the footer of the UITableView.
What I want is to clear all the edited values and refresh all the UITextFields in the UITableView when the user clicks the UIButton.

I can easily enough remove all objects from the valueArray but I can't figure out how to refresh all the UITableView cells to reflect the changes.

Any help is appreciated.
lq

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

哽咽笑 2024-11-03 19:15:33

我相信你正在寻找的是

[tableView reloadData];

I believe what you're looking for is

[tableView reloadData];
写下不归期 2024-11-03 19:15:33

你的解决方案感觉很奇怪。 Filipe 是对的,正确的方法是使用 [wordsTableView reloadData],这将导致为每个可见单元格调用 tableView:cellForRowAtIndexPath:。当您滚动表格时也会调用该方法,因此如果 reloadData 不起作用,您可能还会遇到错误,因为在更改数据和滚动时数据无法正确更新。在您的clearValues方法中,您通过调用tableView:cellForRowAtIndexPath:来执行相同的操作。

我认为真正的问题在于您的 tableView:cellForRowAtIndexPath: 实现。该方法通常有 2 个部分。首先,您创建或回收一个单元格以获取类似以下内容的引用:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}

在 if 语句中通常是您应该向单元格添加子视图的唯一位置。如果 dequeueReusableCellWithIdentifier: 返回一个单元格,则它应该已经具有子视图。

然后,在 if 语句之后,填充或更新子视图的内容。原始代码的问题在于,它正在填充文本字段并将其添加为子视图,假设单元格中还没有文本字段。因此,您的 tableView:cellForRowAtIndexPath: 应该看起来更像这样:

int textFieldTag = 100;

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(158, 6, 148, 24)];
    [textField setTag:textFieldTag];
    [textField setDelegate:self];
    [cell addSubview:textField];
    [textField release];
}

UITextField *textField = [cell viewWithTag:textFieldTag];
NSString *strReplacement = [valueArray objectAtIndex:indexPath.row];

if (([strReplacement length] != 0) {
    textField.text = strReplacement;
} else {
    textField.placeholder = @"Add Value";
}

看起来您可能将 textField 的标记值设置为行号,大概这样您就可以在 UITextFieldDelegate 中使用它。这也可能导致错误,就像第 1 行的单元格被 dequeueReusableCellWithIdentifier: 回收并成为第 12 行一样,它将具有意外的标记值。即使现在没有发生,它也是一个等待发生的错误,并且很难排除故障。

Your solution feels weird. Filipe's right that the correct way to do it is with [wordsTableView reloadData], which will cause tableView:cellForRowAtIndexPath: to be called for each visible cell. That method is also called as you scroll through the table, so if reloadData isn't working, you're probably also going to end up with bugs with data not updating correctly as you change it and scroll. In your clearValues method, you're doing the same thing by calling tableView:cellForRowAtIndexPath:.

I think the real problem is in your tableView:cellForRowAtIndexPath: implementation. That method generally has 2 sections. First, you create or recycle a cell to get a reference with something like:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}

Inside that if statement is generally the only place you should be adding subviews to your cell. If dequeueReusableCellWithIdentifier: returns a cell, it should already have the subview.

Then, after that if statement, you populate or update the contents of the subviews. The problem with your original code is that it's populating the text field and adding it as a subview, assuming there isn't already a text field in the cell. So your tableView:cellForRowAtIndexPath: should look something more like this:

int textFieldTag = 100;

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(158, 6, 148, 24)];
    [textField setTag:textFieldTag];
    [textField setDelegate:self];
    [cell addSubview:textField];
    [textField release];
}

UITextField *textField = [cell viewWithTag:textFieldTag];
NSString *strReplacement = [valueArray objectAtIndex:indexPath.row];

if (([strReplacement length] != 0) {
    textField.text = strReplacement;
} else {
    textField.placeholder = @"Add Value";
}

It looks like you may be setting the textField's tag value to the row number, presumably so you can use it in the UITextFieldDelegate. That could also lead to bugs, as if the cell from row 1 is recycled by dequeueReusableCellWithIdentifier: and becomes row 12, it's going to have an unexpected tag value. Even if it doesn't happen now, it's a bug waiting to happen, and will be tricky to troubleshoot.

╭⌒浅淡时光〆 2024-11-03 19:15:33

Filipe 的解决方案也应该有效,但是,应尽可能避免调用 reloadData,因为调用此方法会产生很高的性能开销。

您需要一些类来引用屏幕/表格中的 UIButton 实例以及所有 UITextField 实例。听起来对于您的 UITableView 控制器子类来说是完美的工作!

在上面的代码中,为什么不将您创建的每个 UITextField 添加到 UITableView 控制器中的文本字段 NSArray 中?然后,当用户按下 UIButton 时,操作可以调用控制器类中的某些方法,该方法循环遍历 NSArray 中的所有 UITextField 元素将每个实例的 text 属性设置为 @""

警告:如果您要重复使用单元格,则可能必须确保控制器的 UITextFieldsNSArray 正确更新。

Filipe's solution should also work, however, calling reloadData should be avoided wherever possible as calling this method has a high performance overhead.

You need some class that has a reference to both the UIButton instance as well as all the instances of the UITextField that you have on the screen/in the table. Sounds like the perfect job for your UITableView controller subclass!

In your code above, why don't you also add each UITextField that you create to an NSArray of text fields that lives in your UITableView controller? Then when the user presses the UIButton, the action can call some method in your controller class, which loops through all the UITextField elements in the NSArray setting the text property of each instance to @"".

Warning: If you're reusing cells then you may have to ensure that the controller's NSArray of UITextFields is being updated properly.

魔法唧唧 2024-11-03 19:15:33

经过几个小时的反复试验,我想出了这个解决方案。 UIButton“全部清除”调用以下方法:

- (IBAction)clearValues:(id)sender {

    // count the number of values in the array (this is the same as the number of rows in the table)
    int count = [valueArray count];

    // remove all values from the array (deletes any user added values):
    [self.valueArray removeAllObjects];

    UITableViewCell *cell;
    UITextField *textField;

    // loop through each row in the table and put nil in each UITextField:
    for (NSUInteger i = 0; i < count; ++i) {

        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
        cell = [self.wordsTableView cellForRowAtIndexPath:indexPath];

        // NOTE: Make sure none of your tags are set to 0 since all non-tagged objects are zero.
        // In table construction, your textFieldTags should be: textField.tag=indexPath.row+1;

        textField = (UITextField*)[cell viewWithTag:i+1];
        textField.text = nil;

    }

}

After a few hours of trial and error, I came up with this solution. The UIButton "Clear All" invokes the following method:

- (IBAction)clearValues:(id)sender {

    // count the number of values in the array (this is the same as the number of rows in the table)
    int count = [valueArray count];

    // remove all values from the array (deletes any user added values):
    [self.valueArray removeAllObjects];

    UITableViewCell *cell;
    UITextField *textField;

    // loop through each row in the table and put nil in each UITextField:
    for (NSUInteger i = 0; i < count; ++i) {

        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
        cell = [self.wordsTableView cellForRowAtIndexPath:indexPath];

        // NOTE: Make sure none of your tags are set to 0 since all non-tagged objects are zero.
        // In table construction, your textFieldTags should be: textField.tag=indexPath.row+1;

        textField = (UITextField*)[cell viewWithTag:i+1];
        textField.text = nil;

    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文