Why is becomeFirstResponder not working?
Asked Answered
T

3

22

I added a modal using AGWindowView. Inside the modal view (built using IB), there is a textfield. The textfield has been connected to an outlet.

This doesn't work:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self.placesTextField becomeFirstResponder];
}

The call to becomeFirstResponder doesn't work and the keyboard doesn't show up.

This works:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self.placesTextField performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0];
}

However, if I manually send a message using performSelector:withObject:afterDelay it works. Why is this method not being determined until runtime?

Toby answered 26/11, 2013 at 4:57 Comment(11)
Have you set the delegates properly ?Aperiodic
Yup, through IB AND code. Sanity check +.Toby
Yes. It doesn't work.Toby
try this : call becomefirstresponder on main thread , this might helpAperiodic
I already have a working solution. I just need to know why it wouldn't work if I directly call [self.placesTextField becomeFirstResponder];Toby
Are you using presenting model view controller with this controller ?Aperiodic
Yes. I'm using AGWindowView.Toby
If you are using presentmodelViewController , then it always freezes the app till the whole presenting of view is not done, thats why some instructions written in initial methods are not called, in this scenario perfromselector after delay helpsAperiodic
I don't quite agree with that statement. Also, my delay value is 0, so it's instantaneous.Toby
No, it's not instantaneous, it will happen in the next runloop.Chalcedony
You can also use dispatch_main_queue with no delay, or NSOperation.performOperationWithBlock. That way you avoid the awkwardness of selector syntax and get normal compiler method checking. I wish I understood WHY I had to do this though.Hyrax
M
7

Seems somehow in iOS7, view/object is not attached in view hierarchy / window yet. So calling method over object fails. If we put some delay and it is working that means at that moment objects are attached to window.

As per Apple,

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.

You may call this method to make a responder object such as a view the first responder. However, you should only call it on that view if it is part of a view hierarchy. If the view’s window property holds a UIWindow object, it has been installed in a view hierarchy; if it returns nil, the view is detached from any hierarchy.

For more details see UIResponder Class Reference.

Mogul answered 26/11, 2013 at 5:36 Comment(0)
B
1

There is a big difference between your first and second method.

Per the delay parameter of performSelector:withObject:afterDelay:

The minimum time before which the message is sent. Specifying a delay of 0 does not necessarily cause the selector to be performed immediately. The selector is still queued on the thread’s run loop and performed as soon as possible.

The second method will wait until an appropriate time and perform becomeFirstResponder.

Breakfront answered 14/3, 2016 at 13:3 Comment(1)
this comment explains the discrepancy perfectly. The issue is the timing of the call and the case of it being performed instantly in the first case and failing or 'at some time later' in the second case and succeeding.Houck
G
0

call becomeFirstResponder like below, maybe it works for you too coz it did work for me

[textView performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0];
Gwyngwyneth answered 1/2, 2023 at 8:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.