I'm using an inputAccessoryView with a next and a done button, to help manage to keyboard. However, I've run into a problem, where every so often the app will crash with an EXC_BAD_ACCESS error when the keyboard is being closed with resignFirstResponder.
The code that I'm using is below
- (void)keyboardNextClicked {
int i = 0;
for(ALFReportField *field in _reportfields) {
UITextView *textView = field.txtvValue;
if(textView.isFirstResponder) {
if(_reportfields.count > i + 1){
ALFReportField *nextField = _reportfields[i + 1];
[nextField.txtvValue becomeFirstResponder];
}
else {
// [textView performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.125];
[textView resignFirstResponder];
}
return;
}
i++;
}
}
-(void)keyboardDoneClicked {
for(ALFReportField *field in _reportfields) {
UITextView *textView = field.txtvValue;
if(textView.isFirstResponder) {
// [textView performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.125];
[textView resignFirstResponder];
return;
}
}
}
The commented lines was an attempt to resolve the problem by delaying the resignFirstResponder call (a solution that I read about elsewhere), but it didn't work.
The app runs through the code without problem, down to the return, throwing no errors in my code. However, just after it has exited by code, I get an error with the following stacktrace:
objc_retain + 10, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x1178f8b9)
frame #0: 0x33b5067a libobjc.A.dylib`objc_retain + 10
frame #1: 0x26c3e1fa UIKit`-[UIResponder _preserveResponderOverridesWhilePerforming:] + 122
frame #2: 0x27125230 UIKit`-[UIInputWindowController invalidateInputAccessoryView] + 112
frame #3: 0x27125b58 UIKit`-[UIInputWindowController changeToInputViewSet:] + 972
frame #4: 0x271208a2 UIKit`__77-[UIInputWindowController moveFromPlacement:toPlacement:starting:completion:]_block_invoke886 + 414
frame #5: 0x268e59b4 UIKit`-[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 540
frame #6: 0x268e5494 UIKit`-[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 204
frame #7: 0x268e538e UIKit`-[UIViewAnimationState animationDidStop:finished:] + 78
frame #8: 0x2617aa50 QuartzCore`CA::Layer::run_animation_callbacks(void*) + 252
frame #9: 0x3425bbd6 libdispatch.dylib`_dispatch_client_callout + 22
frame #10: 0x34269f70 libdispatch.dylib`_dispatch_main_queue_callback_4CF$VARIANT$mp + 1524
frame #11: 0x2277e96c CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
frame #12: 0x2277ce66 CoreFoundation`__CFRunLoopRun + 1574
frame #13: 0x226d0118 CoreFoundation`CFRunLoopRunSpecific + 520
frame #14: 0x226cff04 CoreFoundation`CFRunLoopRunInMode + 108
frame #15: 0x2b886ac8 GraphicsServices`GSEventRunModal + 160
frame #16: 0x26912f14 UIKit`UIApplicationMain + 144
* frame #17: 0x000eee44 Alfix app`main(argc=1, argv=0x00584a48) + 108 at main.m:14
Anyone have any idea what is going wrong? I'm not touching the textviews in any way, shape or form during this process, except for the resignFirstResponder call. That, coupled with the stacktrace makes me think that it must be InputAccessoryView that is causing the error.
Edit:
The input accessory view is created through the general override method on the viewcontroller's view:
- (UIView *)inputAccessoryView {
CGRect frame = CGRectMake(0, 0, 320, 36);
UIView *inputAccessoryView = [[UIView alloc] initWithFrame:frame];
UIButton *btnNext = [inputAccessoryView addButton];
UIButton *btnDone = [inputAccessoryView addButton];
[inputAccessoryView setHeight:36];
[btnNext topInset:0 leftInset:0 bottomInset:0];
[btnNext rightOffset:0 to:btnDone];
[btnDone topInset:0 rightInset:0 bottomInset:0];
[btnNext setWidthEqualTo:btnDone];
[inputAccessoryView setBackgroundColor:[UIColor colorWithHexString:@"#DCDFE3"]];
[btnNext setTitle:@"Next" forState:UIControlStateNormal];
[btnNext setTitleColor:kColorBlack forState:UIControlStateNormal];
[btnDone setTitle:@"Done" forState:UIControlStateNormal];
[btnDone setTitleColor:kColorBlack forState:UIControlStateNormal];
[btnNext addTarget:self action:@selector(keyboardNextClicked) forControlEvents:UIControlEventTouchUpInside];
[btnDone addTarget:self action:@selector(keyboardDoneClicked) forControlEvents:UIControlEventTouchUpInside];
return inputAccessoryView;
}
答案 0 :(得分:2)
事后看来,问题很明显。在创建输入附件视图时,我将IA视图传递给键盘,但是我没有将它存储在任何地方。因此,当键盘关闭时,IA视图被取消分配,从而导致崩溃和错误消息。
首次创建时,将inputAccessoryView保存为属性,解决了这个问题。
- (UIView *)inputAccessoryView {
CGRect frame = CGRectMake(0, 0, 320, 36);
_inputAccessoryView = [[UIView alloc] initWithFrame:frame];
...
然后当键盘关闭时它不会被取消分配,一切正常。