beFirstResponder запускает UIKeyboardDidHideNotification

Одной из целей моего приложения является управление несколькими пользовательскими представлениями ввода (из перьев) вместе с обычной системной клавиатурой. То или иное всегда будет присутствовать. (В примере кода я управляю только одним пером + системной клавиатурой).

При замене клавиатур я хочу сохранить эффект выдвижения/выдвижения, который вы видите на системной клавиатуре. Чтобы получить скользящую анимацию как для пользовательской, так и для системной клавиатуры, я resignFirstResponder из текстового поля и жду, пока клавиатура не будет скрыта. Затем я выполняю команду beFirstResponder, чтобы ввести новую клавиатуру. Я использую UIKeyboardDidHideNotification в качестве триггера для срабатывания функции beFirstResponder и загрузки новой клавиатуры.

Проблема, которую я вижу, заключается в том, что UIKeyboardDidHideNotification срабатывает дважды... один раз при выполнении resignFirstResponder (как и ожидалось) и снова при выполнении beFirstResponder. Я подозреваю, что могу установить какое-то состояние для обнаружения второго уведомления, но я хотел бы понять, почему в первую очередь он вызывает beFirstResponder?

#import "DemoViewController.h"

@interface DemoViewController ()
@property (strong, nonatomic) IBOutlet UITextField *dummyTextField;
@end

@implementation DemoViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[UITextField appearance] setKeyboardAppearance:UIKeyboardAppearanceDark];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];

    [self showNormalKeyboard];
    [_dummyTextField becomeFirstResponder];
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

-(void)keyboardDidHide:(NSNotification*) notification {
    NSLog(@"Keyboard hidden: %@", notification);
    // Executing this next line causes the notification to fire again
    [_dummyTextField becomeFirstResponder];
}

-(void)showAlternateKeyboard{
    _dummyTextField.inputView = [[[NSBundle mainBundle] loadNibNamed:@"AlternateKeyboardView" owner:self options:nil] lastObject];
    [_dummyTextField resignFirstResponder];
}

-(void)showNormalKeyboard{
    _dummyTextField.inputView = nil;
    [_dummyTextField resignFirstResponder];
}

// This is a button on the DemoViewController screen
// that is always present.
- (IBAction)mainButtonPressed:(UIButton *)sender {
    NSLog(@"Main Screen Button Pressed!");
}

// This is a button from the Custom Input View xib
// but hardwired directly into here
- (IBAction)alternateKeyboardButtonPressed:(UIButton *)sender {
    NSLog(@"Alternate Keyboard Button Pressed!");
}

// This is a UISwitch on the DemoViewController storyboard
// that selects between the custom keyboard and the regular
// system keyboard
- (IBAction)keyboardSelectChanged:(UISwitch *)sender {
    if (sender.on){
        [self showAlternateKeyboard];
    } else {
        [self showNormalKeyboard];
    }
}

@end

person Electro-Bunny    schedule 12.03.2014    source источник


Ответы (1)


Я предполагаю, что вы вызываете becomeFirstResponder до того, как предыдущее поле полностью завершило отставку первого респондента. Просто чтобы посмотреть, поможет ли это, попробуйте добавить отложенную производительность:

-(void)keyboardDidHide:(NSNotification*) notification {
    NSLog(@"Keyboard hidden: %@", notification);
    dispatch_async(dispatch_get_main_queue(), ^{
        [_dummyTextField becomeFirstResponder];
    };
}
person matt    schedule 12.03.2014
comment
это сработало. Интересно, есть ли способ синхронно убедиться, что resignFirstResponder завершен? - person Electro-Bunny; 13.03.2014
comment
Собственно, это именно то, чем мы здесь занимаемся. Мы просто прокручиваем один оборот цикла выполнения, чтобы все успокоилось, прежде чем продолжить. На самом деле в этом нет ничего асинхронного. Это минимальная пауза, которая возобновляется, как только завершается выполнение всего кода. - person matt; 13.03.2014