我有一个使用自定义单元格的 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
有一个更简单的方法。在 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/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |