becomeFirstResponder works in viewDidAppear but doesn't work in viewDidLoad

十年热恋 提交于 2019-12-03 10:28:13

You should call in viewDidLayoutSubviews(), the code below set textField becomeFirstResponder only at the first time view layout subviews, and it should be.

var isFirstLayout: Bool = true
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if isFirstLayout {
        defer { isFirstLayout = false }
        textField.becomeFirstResponder()
    }
}

Possibly it does not work in viewDidLoad, as view does not added into view hierarchy yet. But according to apple documentation becomeFirstResponder should be called only on objects attached to UIWindow:

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.

So, i assume, the best place to achieve necessary behavior is to place call into viewWillAppear method.

Update.

So, in viewWillAppear controller's view not yet attached to UIWindow... it only notify, that view will be added to view hierarchy

It may be some tricky, but you can make some small delay in viewWillAppear:

 - (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    double delayInSeconds = 0.05;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^{ 
        make first responder here
    });
 }

But I believe there is should be a better solution

all the IBOutlet objects are loaded in viewDidLoad,if you are calling the method in viewDidLoad then that action not performed because before the objects are loaded we can't do anything that's whybetter to write that code in

-(void)viewWillAppear:(BOOL)animated{
//write here
} 

then it works fine.

This will help:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.quantifyTextField becomeFirstResponder];
    });
}

Making text field/view first responder should be done after all UIViewController animations, which take place when view is loaded and presented. So the best place is viewDidAppear.

Write viewWillAppear instad of viewDidAppear/viewDidLoad.

BecauseviewWillAppear method is call at the time of View will appear (in process), for more information about viewWillAppear read this official Document.

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

I know it is a bit old thread, but I think it can help someone that is facing some keyboard issue when adding this code.

Remember to set the textfield delegate to nil in viewWillDisappear, otherwise the keyboard will not be shown again if you pop/dismiss the view controller without closing the keyboard.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!