抬头编辑:我在下面发布了(简单)答案。无需浪费时间查看所有这些代码。另请参阅杰克劳伦斯的回答中的结构建议。
我在 tableViewCell 中设置了一个 UITextField,它以enabled = NO
. 后来它被更改为,enabled = YES
以便它可以成为第一响应者并调用键盘等。
但是一旦enabled
是NO,它就再也不会是YES了:
tf.enabled = YES;
printf(" Is tf enabled? %d", [tf isEnabled]); // this prints 0 — it refuses to be re-enabled.
更奇怪的是,如果我继承 UITextField 并给它一个简单的自定义方法,我可以从控制器成功调用该方法——之前 enabled
设置为 NO。一旦enabled
为否,调用自定义方法什么也不做。没有警告或异常;它只是不运行。
所以问题不仅仅是响应者链的一些问题。曾经禁用的文本字段的行为就像一个黑洞。
enabled
我确实看过 Apple 的单元格中可编辑文本字段的演示,“TaggedLocations”,他们完全不受惩罚地摆弄:nameField.enabled = NO;
一切都nameField.enabled = YES;
像发条一样。
还有另一条线索:UIControl 类引用说:“如果启用状态为 NO,则控件会忽略触摸事件,子类可能会以不同方式绘制。” 但是拒绝重新启用?拒绝接受方法调用?我不明白。
好吧,这可能比你真正想看的要多,但希望其中隐藏着一些线索。
下面是 UITextField 子类的 h 和 m 文件:
#import "FooNameFieldForCell.h"
@implementation FooNameFieldForCell
- (BOOL) canBecomeFirstResponder {
printf("\nCBFR called, self.enabled is %d.", self.enabled);
if (self.enabled)
return YES;
else
return NO;
}
- (BOOL) canYouHearMe:(id)sender {
printf("Yes, I hear you.");
return YES;
}
@end
#import <UIKit/UIKit.h>
@interface FooNameFieldForCell : UITextField {
}
- (BOOL) canYouHearMe:(id)sender;
@end
这是 cellForRow 和操作方法:
BOOL bPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);
// Cell Which Layout
NSString *identifier = nil;
UITableViewCell *cellFooList = nil;
switch (indexPath.row) {
case 0:
// this textfield is in row 0
identifier = bPortrait ? @"cellFooListName_portrait" : @"cellFooListName_landscape";
cellFooList = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cellFooList)
cellFooList = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
break;
// other rows…
}
// Foo
Foo *Foo = [self.frcFoosAllReg_byName.fetchedObjects objectAtIndex:indexPath.section];
// Cell Fill
switch (indexPath.row) {
case 0: {
if (cellFooList.tag == 1) {
for (UIView *subview in cellFooList.subviews) {
if (subview.tag == 2) {
((FooNameFieldForCell *)cellFooList).text = Foo.FooName;
break;
}
}
break;// dequeued cell, already done
}
// button "Edit"
// (Yes, I know you’re supposed to put this on the navBar, but as a user I have never liked that metaphor. I’m doing the editability by section/row.)
UIButton *btnEditFooName = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnEditFooName addTarget:self action:@selector(presentEditFooName:) forControlEvents:UIControlEventTouchUpInside]; // the selector is where I’m trying to enable the textfield
// do button setup & framing
[btnEditFooName setFrame:rectBtnEditFooName];
[cellFooList.contentView addSubview:btnEditFooName];
// TEXTFIELD SETUP FOLLOWS
// do framing
FooNameFieldForCell *tfFooName = [[FooNameFieldForCell alloc] initWithFrame:rectFooName];
[tfFooName canYouHearMe:self]; // custom method runs OK here
tfFooName.text = Foo.FooName;
tfFooName.enabled = NO;
tfFooName.tag = 2; // tag to locate among cell's subviews
[cellFooList.contentView addSubview:tfFooName];
[tfFooName release];
// no row selection allowed
cellFooList.selectionStyle = UITableViewCellSelectionStyleNone;
// tag as done
cellFooList.tag = 1;
break;
// other cases…
}
}
return cellFooList;
}
// Called by the Edit button:
- (void) presentEditFooName:(id)sender {
// Determine which Foo is associated with sender.
if (![sender isKindOfClass:[UIButton class]])
return;
UIView *cell = ((UIButton *)sender).superview.superview;
if (!cell || ![cell isKindOfClass:[UITableViewCell class]])
return;
NSIndexPath *indexPath = [self.tvFooList indexPathForCell:((UITableViewCell *)cell)];
Foo *Foo = [self.frcFoosAllReg_byName.fetchedObjects objectAtIndex:indexPath.section];
FooNameFieldForCell *tfFooName = nil;
for (UIView *subview in cell.subviews) {
if (subview.tag == 2) {
tfFooName = subview;
break;
}
}
// BLACK HOLE
// because tfFooName is nil. But why? It shows up in the cell.
tfFooName.enabled = YES;
[tfFooName becomeFirstResponder];
printf("\ntfFooName can become firstResp? %d", tfFooName.canBecomeFirstResponder); // always prints 0, can't be firstResp
[tfFooName canYouHearMe:self]; // does not run
printf(" Is tfFooName enabled? %d", [tfFooName isEnabled]); // prints 0, still disabled
}
好吧,我的神秘黑洞竟然是——空!好的,现在看起来很明显,特别是因为objective-c 允许调用null。但是我还有另一个谜团:该字段的文本出现在单元格中,那么它怎么可能是 nil 呢?