首页 > 解决方案 > UITableViewController 返回到单元格中的下一个文本字段

问题描述

我有一个 UITableViewController 和一个实现 UITableView 的类。

@interface CreateEditViewController : UITableViewController<UITextFieldDelegate>

@end

我还有一个实现 UITableViewCell 的类,每个 Cell 都包含一个文本字段。

@interface CreateEditCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UITextField *celltextfield;


@end

在我的 TableView 控制器类中,我实现了这三种方法cellForRowAtIndexPathnumberOfRowsInSection并且textFieldShouldReturn

在我的cellForRowAtIndexPath我将每个单元格的文本字段委托分配给 self 并在 switch case 中给每个单元格一个标签。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    CreateEditCell* cell = nil;
    cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.celltextfield.delegate = self;
    cell.celltextfield.returnKeyType = UIReturnKeyNext;

    switch (indexPath.row) {

        case 0:

            cell.celltextfield.tag = 0;
            break;
        case 1:
            cell.celltextfield.tag = 1;
            break;
        case 2:
            cell.celltextfield.tag = 2;
            break;
        case 3:
            cell.celltextfield.tag = 3;
            break;
    }
    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 4;
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    NSInteger nexttag = textField.tag+1;
    UIResponder* nextresponder = [textField.superview viewWithTag:nexttag];
    if(nextresponder){
        [nextresponder becomeFirstResponder];
    }else{
        [textField resignFirstResponder];
        NSLog(@"Nothing to return to");
    }


    return NO;
}

因此,返回下一个文本字段在我之前的设计中起作用,我没有由单元格动态生成文本字段。相反,我在故事板上有单独的文本字段,并在 viewdidload 中分配了它们的标签。但是现在使用当前的设计,当我点击返回按钮而不是转到下一个单元格时,它只会打印“Nothing to return”,这没有意义,因为我有四个单元格(四个文本字段),每个单元格都有自己的独特的标签。所以我的问题是,如何使用我拥有的当前设计返回下一个文本字段。

标签: iosobjective-cuitableview

解决方案


问题是您的设计更改也导致您的文本字段的视图层次结构更改。它们不再是直接的兄弟姐妹,而是托管在表格视图中的单元格中。因此,当您关注一个新的文本字段时,您必须找到承载该文本字段的单元格,而且,此单元格可能不可见,因此您需要先滚动到它。

因此:

- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    NSInteger nexttag = textField.tag+1;
    if (nexttag < [self.tableView numberOfRowsInSection:0]) {
        NSIndexPath *nextIndexPath = [NSIndexPath indexPathForRow:nexttag inSection:0];
        [self.tableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
        CreateEditCell* cell = [self.tableView cellForRowAtIndexPath:nextIndexPath];
        if (cell == nil) {
            // cell is not displayed at the moment, therefore we 
            // "force-scroll" (without animation) to it
            // and then retrieve it again:
            [self.tableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
            cell = [self.tableView cellForRowAtIndexPath:nextIndexPath];
        }
        [cell.celltextfield becomeFirstResponder];
    }else{
        [textField resignFirstResponder];
        NSLog(@"Nothing to return to");
    }

    return NO;
}

这段代码有点快速和肮脏,因为如果单元格不可见,则无法通过调用来检索它cellForRowAtIndexPath。即使是动画scrollToRowAtIndexPath也无济于事,因为您需要等待显示单元格。所以我的解决方法只是再次滚动,没有动画。

一个更好的解决方案是实现UIScrollViewDelegatescrollViewDidEndScrollingAnimation然后您可以集中文本字段 - 但请注意,只有在滚动是由用户滚动活动引起textFieldShouldReturn而不是由用户滚动活动引起时,您才应该这样做。因此,您将使用一个标志(或更好:自定义委托/闭包),您可以检查它以确定哪种滚动动画结束了。


推荐阅读