質問

One goal of my app is to manage multiple custom input views (from nibs) along with the regular system keyboard. One or the other will always be present. (In the example code I am only managing a single nib + the system keyboard).

When swapping out the keyboards, I want to preserve the slide-in/slide-out effect you see with the system keyboard. To get the sliding animation for both the custom keyboard as well as the system keyboard I resignFirstResponder from the textfield and wait until the keyboard is hidden. Then I execute a becomeFirstResponder to bring in the new keyboard. I use the UIKeyboardDidHideNotification as a trigger to fire becomeFirstResponder and load the new keyboard.

The problem I see is that the UIKeyboardDidHideNotification is firing twice... once when executing resignFirstResponder (as expected) and again when becomeFirstResponder is executed. I suspect I can put in some state to detect the second notification, but I would like to understand, why becomeFirstResponder is causing it to fire in the first place?

#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
役に立ちましたか?

解決

My guess is that you are calling becomeFirstResponder before the previous field has fully finished resigning first responder. Just to see if it helps, try adding some delayed performance:

-(void)keyboardDidHide:(NSNotification*) notification {
    NSLog(@"Keyboard hidden: %@", notification);
    dispatch_async(dispatch_get_main_queue(), ^{
        [_dummyTextField becomeFirstResponder];
    };
}

他のヒント

@interface MainViewController : UIViewController

@property (nonatomic, retain) IBOutlet UITextField *textField;
@property (nonatomic, retain) IBOutlet UISwitch *keyboardSwitch;
@property (nonatomic, retain) IBOutlet UISwitch *textFieldSwitch;


- (IBAction)toggleKeyboardVisibility;

@end


#import "MainViewController.h"

@implementation MainViewController
@synthesize textField, keyboardSwitch, textFieldSwitch;

- (void)viewDidLoad
{
    [super viewDidLoad];
}

/**
 * Show keyboard as soon as view appears
 *
 */
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.textField becomeFirstResponder];
}

/**
 * Modify the hidden property of our text field
 *
 */
- (IBAction)toggleTextFieldVisibility
{
    if (self.textFieldSwitch.on)
        self.textField.hidden = NO;
    else
        self.textField.hidden = YES;
}

/**
 * Change the first responder status of the keyboard
 *
 */
- (IBAction)toggleKeyboardVisibility
{
    if (self.keyboardSwitch.on)
        [self.textField becomeFirstResponder];
    else
        [self.textField resignFirstResponder];
}

@end
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top