Cannot set searchBar as firstResponder

2020-01-27 02:46发布

I have a searchBar I'm setting in a tableviewcontroller. i've referenced this similar question UISearchBar cannot become first responder after UITableView did re-appear but am still unable to set it as first responder. In .h file:

@property (strong, nonatomic) UISearchController *searchController;
@property (strong, nonatomic) IBOutlet UISearchBar *searchBar;

In view didload:

self.searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.hidesNavigationBarDuringPresentation = NO;

self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.tableView.tableHeaderView = self.searchController.searchBar;

And in viewDidAppear:

-(void)viewDidAppear:(BOOL)animated {
  [self.searchController setActive:YES];
  [self.searchController.searchBar becomeFirstResponder];
  [super viewDidAppear:animated];
}

When I segue to the view the searchBar animates, but no keyboard appears.

18条回答
聊天终结者
2楼-- · 2020-01-27 03:33

The function searchController.searchBar.becomeFirstResponder() must be called in the main thread and after searchController.active = true in the viewDidLoad method. Here're the full solution. It works on iOS 9.3

override func viewDidAppear(animated: Bool) {
  super.viewDidAppear(animated)
  searchController.active = true
  Async.main {
    self.searchController.searchBar.becomeFirstResponder()
  }
}
查看更多
霸刀☆藐视天下
3楼-- · 2020-01-27 03:33

Very similar to other answers, but I had to access the main queue in the ViewDidAppear. The SearchBarController can't be acted upon until the View appears and then can only be done so in the main queue for UI:

searchController.active = true  // doubtful whether this is needed

        dispatch_async(dispatch_get_main_queue(), {
            self.searchController.searchBar.becomeFirstResponder()
        });
查看更多
闹够了就滚
4楼-- · 2020-01-27 03:33

Based on @mislovr's solution, the 0.1 delay was not long enough. Here is my updated code to that answer.

func presentSearchController() {
    searchController.isActive = true

    Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak searchController] timer in
        guard let searchController = searchController else {
            timer.invalidate()
            return
        }

        if searchController.searchBar.canBecomeFirstResponder {
            searchController.searchBar.becomeFirstResponder()
            timer.invalidate()
        }
    }
}
查看更多
走好不送
5楼-- · 2020-01-27 03:36

To me, there’s a quite big lag when using viewDidAppear. It can be better to use becomeFirstResponder asynchronously in viewDidLoad (tested with iOS 10, Swift 3):

override func viewDidLoad() {
    super.viewDidLoad()

    DispatchQueue.main.async {
        searchController.searchBar.becomeFirstResponder()
    }
}
查看更多
We Are One
6楼-- · 2020-01-27 03:37

Swift 4, iOS 11

It works for me

// 1.
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    resultSearchController.isActive = true
}

// 2. ->> UISearchControllerDelegate
func didPresentSearchController(_ searchController: UISearchController) {

    DispatchQueue.main.async {
        searchController.searchBar.becomeFirstResponder()
    }
}
查看更多
Fickle 薄情
7楼-- · 2020-01-27 03:40

This is what it worked for me in Swift 3.

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.perform(#selector(self.showKeyboard), with: nil, afterDelay: 0.1)
}

func showKeyboard() {
    self.searchController.searchBar.becomeFirstResponder()
}
查看更多
登录 后发表回答