Ios – UITextField won’t becomeFirstResponder

cocoa-touchiosobjective-c

I'm having a problem getting a textfield to accept the becomeFirstResponder directive.

I'm providing a custom mechanism to create a title in the navigation bar. I have another viewcontroller that is successfully using this same technique. On viewDidAppear I fire off:

- (void)addTitleTextField
{
    CGRect textFrame = self.parentViewController.navigationController.navigationBar.frame;
    textFrame.size.width = 300.0;
    textFrame.origin.y = (768.0 - 300.0)/2;
    textFrame.size.height = 30.0;
    textFrame.origin.x = 7.0;
    self.titleTextField = [[UITextField alloc] initWithFrame:textFrame];
    self.titleTextField.placeholder = NSLocalizedString(@"New Multiple Choice Quiz", @"New Multiple Choice Quiz");
    self.titleTextField.borderStyle = UITextBorderStyleRoundedRect;
    self.titleTextField.font = [UIFont boldSystemFontOfSize:20.0];
    self.titleTextField.textAlignment = NSTextAlignmentCenter;
    self.titleTextField.backgroundColor = [UIColor whiteColor];
    self.titleTextField.textColor = [UIColor blackColor];
    self.titleTextField.delegate = self;
    [self.titleTextField setAutocorrectionType:UITextAutocorrectionTypeNo];
    self.titleTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
    [self.titleTextField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
    self.activeTextField = self.titleTextField;
    self.parentViewController.navigationItem.titleView = self.titleTextField;
    [self.titleTextField becomeFirstResponder];
}

self.titleTextField will allow me to set the text value, but if you check using canBecomeFirstResponder it returns NO. As you can see I am setting this on the parentViewController. I've tried using a delegate to attempt to get the parentViewController to set it. When I do the delegate and check whether the textField canBecomeFirstResponder it returns YES, but I'm still unable to make it accept the firstResponder order. Any ideas? The Docs say "A responder object only becomes the first responder if the current responder can resign first-responder status (canResignFirstResponder) and the new responder can become first responder".

Best Solution

Are you telling the UITextField to become selector on a background thread?

[textField performSelectorOnMainThread:@selector(becomeFirstResponder) withObject:nil 
  waitUntilDone:YES];

Rationale: Calling UIKit methods (ie updating the view) on a method other than the main thread won't work. . this could be happening. (It is not clear where the addTitleTextField method is being called from).

Is there another first responder that needs some time to resign?

[textField performSelectorOnMainThread:@selector(becomeFirstResponder) withObject:nil afterDelay:0.0];

Rationale: If another field is hanging onto first responder (or in the process of resigning it), it will give it time to clean up an resign, by waiting until the next run-loop. . . . . usually the next run-loop will be enough time for the previous responder to clean up, or you could try a short delay like 0.05.