【问题标题】:How to loop Through each UITextfield of a Section?如何循环遍历一个部分的每个 UITextfield?
【发布时间】:2014-02-24 20:19:18
【问题描述】:

今天早些时候,我向question 询问了有关文本字段的问题。现在我被困在如何遍历每个 UITextFields。

如何循环遍历 Section 的每个 UITextfield ?

到目前为止,这是我的代码:

- (IBAction)ForwardReport:(id)sender {
    NSLog(@"PRESSED");
    for (UITableViewCell *cell in [self.tableView.indexPathsForVisibleRows]) {
        if ([cell isKindOfClass:[UITextField class]]) {
            UITextField *textField = (UITextField *)cell;
            NSLog(@"UITEXTFIELD TEXT = %@", textField.text);
        }
    }
}

我尝试关注this answer,但不幸的是我的代码无法编译。

我不确定如何在 UItableView 委托之外访问第 1 部分(第二部分)。

我想遍历每个 UITextfield,并检索其文本值。

请指教:

这是一个屏幕截图

我想我的另一个选择是为每个字段创建 IBoutlets,并有一堆 if/else 语句,但听起来有点乱......

【问题讨论】:

    标签: ios iphone objective-c uitableview


    【解决方案1】:

    我的建议是不这样做。由于可重用性,您不能依赖嵌入在 tableView 单元格中的 UITextField 的内容。

    您的视图控制器应该直接绑定到模型,因此,更改 textField 中的文本应该立即更新您的模型,因此,当您滚动并重用单元格时,会分配正确的值。当您点击“前进”时,您只需查询模型的内容(无论如何,这可能是一个简单的NSMutableArray)。

    让我们添加一个 NSMutableArray,其中包含与 textField 一样多的空字符串(例如 5 个):

    - (instancetype)initWithWhatever...
    {
        self = [super initWithWhatever];
    
        if (self)
        {
            _textFieldValues = [NSMutableArray arrayWithCapacity:5];
    
            for (NSInteger i=0; i < 5; i++)
            {
                _textFieldValues[i] = @"";
            }
        }       
    
        return self;
    }
    

    确保每个文本字段都指向 cellForRowAtIndexPath: 上的 viewController。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        ...        
    
        myCell.textField.text     = _textFieldValues[indexPath.row];
        myCell.textField.tag      = 100 + indexPath.row;
        myCell.textField.delegate = self;
    
        return myCell
    }
    

    标签用于识别每个单元格,其他选项是创建自己的UITextField 子类或使用自定义setValueForKey:。

    无论您选择什么,当您获得委托方法 (UITextFieldDelegate) 时,检查您的首选方法,在我的情况下标记:

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        NSString *replaced = [textField.text stringByReplacingCharactersInRange:range withString:string];
    
        _textFieldValues[(textField.tag - 100)] = replaced;
    
        return YES;
    }
    

    这将使模型始终保持最新,并且您无需迭代文本字段,只需遍历数组即可:

    // Method that gets called when hitting forward
    - (IBOutlet)didPressForwardButton:(UIButton*)sender
    {
        for (NSString *text in _textFieldValues)
        {
            NSLog(@"UITEXTFIELD TEXT = %@", text);
        }
    }
    

    课程:使用UITableView 时,您应该始终将视图上的内容映射到模型上的内容,并立即更新,您不能依赖视图来保存数据。事实上,这应该扩展到你在 iOS 中所做的任何事情,视图是用于展示的。如果您不能立即修改真实模型,则必须将其封装在“事务”中间对象中,然后更新真实模型。

    【讨论】:

    • 所以基本上 finalString 包含所有 5 个 UIExfield 值?
    • 不,finalString(现在称为replaced,以避免混淆)是从textField: shouldChangeCharactersInRange替换的字符串,所有文本字段的信息都位于数组_textFieldsValues内。
    • 很有趣,你能告诉我如何遍历那个数组吗?抱歉,我从未见过它带有标签/索引
    • 数组只是一个普通数组,我只是使用标签来识别每个单独的文本字段,如果你注意到了,我只是加了 100 并减去了 100 以避免与其他标签冲突。
    • @AlPacino 好了,我说得更具体了。
    【解决方案2】:

    您不应该在单元格中而是在单元格的子视图中搜索 UITextField。

    尝试关注

    - (IBAction)ForwardReport:(id)sender {
        NSLog(@"PRESSED");
        for (UITableViewCell *cell in self.tableView.visibleCells) {
            for (UIView *subview in [cell.contentView subviews])
                if ([subview isKindOfClass:[UITextField class]]) {
                    UITextField *textField = (UITextField *) subview;
                    NSLog(@"UITEXTFIELD TEXT = %@", textField.text);
                }
            }
        }
    }
    

    【讨论】:

    • 第一个 for 循环无法编译,我相信是因为 [self.tableView.indexPathsForVisibleRows] 错误...不知何故我只需要循环通过 indexPath.section == 1 但不确定如何在 IBAction 内部执行此操作
    • 你是对的。 visibleCells 应该在这里使用。请检查更新的答案。
    • 仍然无法编译,你知道我怎样才能让这个stackoverflow.com/a/5644695/3205189 只循环第 1 节吗?
    • 好的。我刚刚打开 Xcode 并检查了代码。应使用self.tableView.visibleCells 而不是[self.tableView.visibleCells]。我已经更新了答案
    • 即使您知道该怎么做,也很难编写whiteout IDE。犯一些愚蠢的错字的大好机会。
    【解决方案3】:

    在 AVT 的回答中,去掉 for 循环中 self.tableView.visibleCells 周围的括号。然后它会读取

    for (UITableViewCell *cell in self.tableView.visibleCells)
    

    那么下一个 for 循环应该是真正使用单元格内容视图的子视图:

    for (UIView *subview in [cell.contentView subviews])
    

    不过,这些都是小问题。

    还有一个更重要的设计问题。您不应该遍历当前可见的单元格。表格视图单元格是瞬态的。如果用户将表格视图单元格滚动出屏幕,则其内容将被丢弃 - 并丢失。

    当用户输入信息时,您应该从单元格中的视图对象收集信息:开关和分段控件应该连接到可以立即将用户更改保存到数据模型中的插座。同样对于文本字段,您需要设置一个委托,并在用户输入完成后立即收集用户的输入并将其保存到数据模型中。

    【讨论】:

    • 你说得对,现在可以编译了,对不起,我是新手,所以我没有完全理解最后一段。
    • 快速问题:这段代码如何只循环通过第 1 部分,我没有看到该检查,因为我在其他部分有 Textfield?我想确保它不在其他部分中。
    • @Duncan C 的意思是(如果我错了,请纠正我):你的类中应该有一个数据结构(可能是一个 NSMutableArray 属性),它包含你想要的数据出现在你的观点中。在您的-forwardReport 方法中,您可以通过调用[self.yourArray objectAtIndex:x] 轻松访问所需的字符串,而不是遍历单元格中包含的所有子视图,这相当复杂并且可能导致其他问题。每当用户更改文本字段中的文本时,您应该通过替换数组中的相应值来更新数据结构。 (->MVC)
    • Mischa,这和我说的差不多。我是说您不能将状态数据存储在表格视图单元格中并期望它持续存在。它不会可靠地工作。表格视图单元格是视图对象。当用户在表格视图单元格的视图中输入数据时,一旦用户完成每次编辑,就应该将它们复制到模型中。然后,当您需要当前数据时,它总是在模型中。是的,对于表格视图的模型来说,数组通常是一个很好的结构。或者可能是一个数组数组,用于分段表视图(部分的外部数组和行的内部数组)
    • @Duncan C,更准确。
    【解决方案4】:

    您的代码中有两个错误。

    第一个问题:

    UITableViewCell *cell in [self.tableView.indexPathsForVisibleRows]
    

    不会工作,因为self.tableView.indexPathsForVisibleRows 返回一个indexPaths 数组,而不是UITableViewCell。试试这个:

    - (IBAction)ForwardReport:(id)sender {
        NSLog(@"PRESSED");
        for (NSIndexPath *indexPath in [self.tableView indexPathsForVisibleRows]) {
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
    
            ...
    
        }
    }
    

    第二个问题:

    UITextField *textField = (UITextField *)cell;
    

    UITextField 不是UITableViewCell 的子类,因此您不能将表格视图单元格转换为文本字段。相反,您必须遍历单元格中包含的所有子视图。所以整个方法是:

    - (IBAction)ForwardReport:(id)sender {
        NSLog(@"PRESSED");
        for (NSIndexPath *indexPath in [self.tableView indexPathsForVisibleRows]) {
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
            for (UIView *subview in cell.subviews)
                if ([subview isKindOfClass:[UITextField class]]) {
                    UITextField *textField = (UITextField *)subview;
                    NSLog(@"UITEXTFIELD TEXT = %@", textField.text);
                }
            }
        }
    }
    

    (注意:我还没有测试过这段代码。)

    【讨论】:

    • 如果投反对票的人能提示这个答案有什么问题,我将不胜感激。
    • 我不知道是谁做的,但我赞成,谢谢你的意见
    • 很好地抓住了滥用 self.tableView.indexPathsForVisibleRows。我错过了。 (已投票)
    猜你喜欢
    • 2014-06-29
    • 1970-01-01
    • 2019-11-20
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多