UITextField 子类在 becomeFirstResponder 抛出奇怪的异常
Posted
技术标签:
【中文标题】UITextField 子类在 becomeFirstResponder 抛出奇怪的异常【英文标题】:UITextField subclass throwing weird exception at becomeFirstResponder 【发布时间】:2012-09-04 11:11:14 【问题描述】:我有由 UINavigatableTextField 组成的字符框。每次输入后,响应者字符应该继承它的继任者。奇怪的是,在输入第一个字符期间,如果用户每次输入字符 'Q' 都会出现不同的异常,例如;
EXC_BAD_ACCESS,或 2012-09-04 14:42:42.600 Kelime Oyunu[6350:707]-[WebScriptObjectPrivate isForShortcutConversion]:无法识别的选择器发送到实例 0x21b870 2012-09-04 14:42:42.606 Kelime Oyunu[6350:707] * 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:'-[WebScriptObjectPrivate isForShortcutConversion]:无法识别的选择器发送到实例 0x21b870 '被抛出。我的代码在下面收到异常,[next becomeFirstResponder] 行
- (void) moveToNextCharacter: (MBNavigatableTextField *) character
dispatch_async(dispatch_get_current_queue(),
^
UIControl *next = [character nextField];
if(next == nil)
[character endEditing:YES];
else if ([next isKindOfClass:[UIButton class]])
[next sendActionsForControlEvents: UIControlEventTouchUpInside];
else
[next becomeFirstResponder];
);
我该如何解决这个问题?提前致谢。
编辑 1:找到一个僵尸 [next resignFirstResponder](感谢 @PhillipMills)
编辑2:原来我的问题是由
引起的- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
// Something done here...
// code block of evil zombie summoner
[textField setText:@"Some text"];
// Something else done here
Profile->Instruments->Zombies 声明在 setText 期间:某个对象被释放(我猜这是之前的字符串)。
我仍然无法解决问题。我的目标是用新的用户输入(replacementString:) 更新上面的 textField。
【问题讨论】:
我认为您需要找出问题所在。单步执行代码(或使用日志消息)找到失败的行,然后引用实际的错误消息。 @DavidH 在评论之前看看我的其他问题。如果你找到答案,我一定会接受的。isForShortcutConversion
是您的一个类中的方法吗? (如果是,请尝试在启用僵尸的情况下运行。)
快速的 Google 搜索表明它是与文本输入相关的私有方法,因此僵尸实验可能会有所帮助,因为您正在使用文本字段并且与 WebScriptObjectPrivate
没有明显的联系。
为什么是 dispatch_get_current_queue
?我宁愿将dispatch_get_main_queue
用于响应者操作,因为这与 UI 状态有关。
【参考方案1】:
所有到 UIKit 对象的消息都必须在主队列上完成。虽然情况可能如此,但此声明:
dispatch_async(dispatch_get_current_queue()
很麻烦,因为我们不知道您在哪个队列上收到消息。将其更改为:
dispatch_async(dispatch_get_main_queue()
所以它绝对清楚。
另外,在这一行下:
UIControl *next = [character nextField];
添加这些语句:
NSLog(@"Character CLASS %@", NSStringFromClass[character class]);
NSLog(@"next CLASS %@", NSStringFromClass[next class]);
确保这些是您认为应该是的。
编辑:关于“unsafe_unretained”的使用:如果 IBOutlet 包含在“self.view”中——这是主要视图——那么你应该在 ios 上使用弱——所以当视图消失。
关于“shouldChangeCharactersInRange”,如果您只是查看字符,则返回 YES。如果您更改文本本身 - 通过直接写入字段/视图,则返回 NO。如果您修改文本然后返回 YES,那么您实质上是在更改控件背后的数据,谁知道会产生什么后果。
【讨论】:
谢谢。正如@A-Live 所建议的那样,将 dispatch_async 队列固定为 dispatch_get_main_queue()。这是我的日志(如果记录不同的结果,尝试了几次): 2012-09-04 16:43:46.179 Kelime Oyunu[4675:f803] Character CLASS MBNavigatableTextField 2012-09-04 16:43:46.180 Kelime Oyunu[4675:f803 ] next CLASS MBNavigatableTextField 所以这些消息是你所期望的——类——它是正确的。然后当'[next becomeFirstResponder];'发送您会崩溃。您需要在所有异常上启用断点和中断,并查看其崩溃的位置。可能是最后一个收到“resign”消息的对象导致了崩溃。 僵尸向我展示了一些位于我的问题“编辑 2”部分下方的信息。还从 textField:shouldChangeCharactersInRange:replacementString: 中删除 [textField setText:@"Some text"] 以解决问题。我的目标仍然是用新的输入替换每个输入。 这不是解决方案,它只是避免问题。因此,如果您进行了该调用,那么“textField 在那时已被释放,或者您在设置文本时没有返回 NO(这可能会使 textField 混淆,可能不会但可能会)。您所有的 MBNavigatableTextFields 都被保留在强引用中?他们也拥有所有对象? 是的,你是对的,这只是在避免问题。仍然是最接近解决方案的事情,你在第一次评论接受解决方案时让我很害怕:)。以上是关于UITextField 子类在 becomeFirstResponder 抛出奇怪的异常的主要内容,如果未能解决你的问题,请参考以下文章
如何在 UITextField 子类中拦截来自键盘的文本输入事件
UITapGestureRecognizer 不适用于 UITextField 的自定义子类