• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - 在 iOS 中,如何在两个单元格中的文本字段之间切换?

[复制链接]
菜鸟教程小白 发表于 2022-12-12 14:01:49 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我有一个使用自定义单元格的 TableView 的应用程序,每个单元格都包含一个文本字段。当用户点击一个单元格时,我想将相应的 textField 置于编辑模式。如果另一个单元格的 textField 已经处于编辑模式,我需要让它 resignFirstResponder 以便我可以保存它的数据,然后使新单元格的 textField 成为 FirstResponder。但是当我在新单元格的 textField 上调用 becomeFirstResponder 时,它返回一个零,表示失败。这似乎是一种困惑的处理方式,但我还没有找到更好的方法。

这是我的 TableViewController 文件的全文,其中去除了很多杂乱无章的内容:

//  TEST_TVC.h
//  TVC_Test
#import <UIKit/UIKit.h>
@interface TEST_TVC : UITableViewController <UITextFieldDelegate>
@end


//  TEST_TVC.m
//  TVC_Test
#import "TEST_TVC.h"
@interface TEST_TVC ()

@property (strong, nonatomic) NSMutableArray * TestData;
@property (strong, nonatomic) UITextField * fieldBeingEdited;
@property (assign, nonatomic) NSInteger cellIndex;
@property (strong, nonatomic) UITableViewCell * cellContainingField;

@end

@implementation TEST_TVC

- (id)initWithStyleUITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Init data for testing the TableView
    self.TestData = [NSMutableArray array];
    for (int i=0; i<25; i++) {
        NSString * title = [NSString stringWithFormat"Field %d", i];
        NSArray * data = [NSArray arrayWithObjects:title, @"*", nil];
        [self.TestData addObject:data];
    }
    self.fieldBeingEdited = NULL;
    self.cellContainingField = NULL;
    self.cellIndex = -1;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableViewUITableView *)tableView
{
    return 1;
}

- (NSInteger)tableViewUITableView *)tableView numberOfRowsInSectionNSInteger)section
{
    return self.TestData.count;
}

- (UITableViewCell *)tableViewUITableView *)tableView cellForRowAtIndexPathNSIndexPath *)indexPath
{
    // Configure the cell...
    NSString *CellIdentifier = @"TVCell";
    NSString * titleText;
    NSString * detailText;
    NSString * detailPlaceholder = @"none";

    // Get the data for this row
    int rowNumber = indexPath.row;
    NSArray * cellData = self.TestData[rowNumber];
    titleText = cellData[0];
    detailText = cellData[1];
    //NSLog(@"cellForRow..., entered row=%d, titleText=%@, detailText=%@", rowNumber, titleText, detailText);

    // Retrieve a pre-built cell to fill in the blanks
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    UILabel * cellTitle = (UILabel *)[cell viewWithTag:98];
    cellTitle.text = titleText;
    UITextField * cellDetail = (UITextField *)[cell viewWithTag:99];
    NSLog(@"cellForRow.. reusing cell with Title=%@ and Detail=%@", cellTitle.text, cellDetail.text);
    NSLog(@"cellForRow.. intended Title=%@, intended Detail=%@", titleText, detailText);
    if (cellDetail == NULL) {
        NSLog(@"cellForRow..; cellDetail = NULL *******************************************");
    }

    // Set default configuration of the cellData UITextField here, and make exceptions later
    cellDetail.placeholder = @"";
    cellDetail.text = @"";
    cellDetail.borderStyle = UITextBorderStyleRoundedRect;
    cellDetail.userInteractionEnabled = NO;
    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.userInteractionEnabled = YES;

    // Configure the cell...
    // based on the data type of the cell's contents

    // Set the cell's editable textField
    if ( [detailText isEqualToString"*"] ) {
        cellDetail.text = @"";
        cellDetail.placeholder = detailPlaceholder;
    } else {
        cellDetail.text = detailText;
    }
    cellDetail.keyboardType = UIKeyboardTypeASCIICapable;
    cellDetail.autocapitalizationType = UITextAutocapitalizationTypeWords;

    return cell;
}


#pragma mark - Table view delegate

- (void)tableViewUITableView *)tableView didSelectRowAtIndexPathNSIndexPath *)indexPath
{
    int rowNumber = indexPath.row;
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
    NSLog(@"didSelectRow.. entered; row=%d, cellData=%@", rowNumber, self.TestData[rowNumber]);
    // The selected cell contains a textField with content to be edited
    // If another cell's textField is currently being edited, save its data before proceding
    UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
    UITextField * cellDetail = (UITextField *)[cell viewWithTag:99];
    NSLog(@"didSelectRow..: curently editing cell at [%p], selected cell at [%p]", self.fieldBeingEdited, cell);
    // if a textField is still in edit mode, show the Responder status of the cell and all in it
    if ( self.fieldBeingEdited != NULL ) {
        [self showCellResponderStatus:self.cellContainingField];
    }

    if ( self.fieldBeingEdited == NULL ) {
        NSLog(@"didSelectRow..: no field is being edited.");
    } else if ( cellDetail == self.fieldBeingEdited ) {
        // the cell selected is the same one being edited
        if ( ![self.fieldBeingEdited isFirstResponder] ) {
            // fieldBeingEdited is NOT the firstResponder. Try to make it the firstResponder.
            BOOL becameFirstResponder = [self.fieldBeingEdited becomeFirstResponder];
            NSLog(@"didSelectRow..: textField at [%p] returned %d from becomeFirstResponder.", self.fieldBeingEdited, becameFirstResponder);
            [self showCellResponderStatus:self.cellContainingField];
        }
    } else if ( cellDetail != self.fieldBeingEdited ) {
        // the cell selected is NOT the one being edited. Save the edited data and release the keyboard
        NSLog(@"didSelectRow..: field in cell with index=%d is being edited. Text=%@", self.cellIndex, self.fieldBeingEdited.text);
        BOOL resignedFirstResponder;
        [self showCellResponderStatus:self.cellContainingField];
        // This method call will log the responder status of this cell and all it is contained within
        //[self showViewHierarchy:self.fieldBeingEdited];
        resignedFirstResponder = [self.fieldBeingEdited resignFirstResponder];
        NSLog(@"didSelect..: resignFirstResponder on [%p] returned %d", self.fieldBeingEdited, resignedFirstResponder);
        //[self showViewHierarchy:self.fieldBeingEdited];
        if (resignedFirstResponder) {
            self.fieldBeingEdited = NULL;
            self.cellContainingField = NULL;
            self.cellIndex = -1; 
        }
    }

    // Enable the textField within the selected cell for in-place editing
    cellDetail.userInteractionEnabled = YES;
    cellDetail.enabled = YES;
    BOOL becameFirstResponder = [cellDetail becomeFirstResponder];
    NSLog(@"didSelectRow..: becomeFirstResponder returned %d", becameFirstResponder);
    if ( becameFirstResponder ) {
        // Update all the references and indexes for the cell and textField being edited.
        self.fieldBeingEdited = cellDetail;
        self.cellContainingField = cell;
        self.cellIndex = rowNumber;
    }

    NSLog(@"didSelectRow.. exit; textFieldBeingEdited.text=%@, cellIndex=%d", self.fieldBeingEdited.text, self.cellIndex);

}

-(BOOL) textFieldShouldBeginEditingUITextField *)textField
{
    NSLog(@"textFieldShouldBeginEditing entered");
    NSLog(@"... returning YES");
    return YES;
}

-(void) textFieldDidEndEditingUITextField *)textField
{
    NSLog(@"textFieldDidEndEditing entered with text: %@, cellIndex=%d", textField.text, self.cellIndex);
    NSInteger cellIndex = self.cellIndex;

    NSMutableArray * cellData = [NSMutableArray arrayWithArray:self.TestData[cellIndex]];
    [cellData replaceObjectAtIndex:1 withObject:textField.text];
    [self.TestData replaceObjectAtIndex:cellIndex withObject:cellData];
    textField.enabled = NO;

    [self.tableView reloadData];
    if ( [textField isFirstResponder] ) {
        NSLog(@"EditFlight(466): textFieldDidEndEditing; textField IS STILL the firstresponder!");
    }
    NSLog(@"textFieldDidEndEditing exit; cellData=%@", cellData);
}

-(BOOL) textFieldShouldReturn: (UITextField *)textField
{
    NSLog(@"textFieldShouldReturn; textField.text=%@", textField.text);
    [textField resignFirstResponder];
    BOOL resignedFirstResponder = [textField resignFirstResponder];
    NSLog(@"textFieldShouldReturn; resignFirstResponder returned %d",resignedFirstResponder);
    return YES;
}

-(void) showCellResponderStatus:(UITableViewCell*)cell
{
    NSLog(@"showCellResponderStatus entered");
    if ( [cell isFirstResponder] ) {
        NSLog(@"cell at [%p] IS first responder", cell);
    }else{
        NSLog(@"cell at [%p] IS NOT first responder", cell);
    }
    NSArray * cellSubViews = [[cell contentView] subviews];
    for ( UIView* uiv in cellSubViews ) {
        if ( [uiv isFirstResponder ]) {
            NSLog(@"subview at [%p] is a %@ and IS first responder", uiv, uiv.class);
        } else {
            NSLog(@"subview at [%p] is a %@ and IS NOT first responder", uiv, uiv.class);
        }
    }
}

-(void) showViewHierarchy:(UIView*) uiv
{
    NSLog(@"View Hierarchy");
    while (uiv != NULL) {
        BOOL isfirst = [uiv isFirstResponder];
        NSLog(@"view at [%p] is a %@, isFirstResponder=%d", uiv, uiv.class, isfirst);
        uiv = uiv.superview;
    }
    NSLog(@"view at [%p] is a %@", uiv, uiv.class);
    NSLog(@"End of view hierarchy");
}

@end



Best Answer-推荐答案


有一个更简单的方法。在 didSelectRowAtIndexPath 中存储对当前单元格的 UITextField 的引用。然后您可以将其设置为第一响应者,处理编辑等。

当您点击一个新单元格以选择它时,代理首先会收到一个 didDeselectRowAtIndexPath。在这里,您可以使用您的 UITextField 引用可以辞职第一响应者,保存任何必要的状态等。然后在新单元格上调用 didDeselectRowAtIndexPath ,您就可以开始了。所以类似于以下内容:

编辑:添加额外代码

// Code additions to Xcode's Master-Detail application template

// Use dynamic prototypes for table cells, custom cell class follows:

// MyCell.h
// Property is auto-synthesized, so there is nothing to see in MyCell.m

@interface MyCell : UITableViewCell
@property (nonatomic, weak) IBOutlet UITextField *tf;
@end



// MasterViewController.m

@interface MasterViewController () {
  NSMutableArray *_objects;
}
@property (nonatomic, weak) UITextField *selectedField;
@end


// this method is called when a cell is DE-selected
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
      [self.selectedField resignFirstResponder];
      // save state, etc if necessary
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyCell * cell = (MyCell *)[tableView cellForRowAtIndexPath:indexPath];
    self.selectedField = cell.tf; // cell.tf is a UITextField property defined on MyCell
    [self.selectedField becomeFirstResponder];
}

关于ios - 在 iOS 中,如何在两个单元格中的文本字段之间切换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18581173/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap