Search code examples
iosuinavigationcontrolleruinavigationbaruisearchbaruisearchcontroller

UISearchController don't push viewcontroller on front but below UISearchController


The behaviour different between automatic presentation UISearchController and present the search controller myself.

@implementation MyViewComtroller

// click search barbutton on right of navigationBar
- (void)searchAction:(id)sender {
    ArticleSearchViewController *searchResultsController = [[ArticleSearchViewController alloc] init];
    UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
    searchController.searchResultsUpdater = searchResultsController;
    searchController.searchBar.delegate = searchResultsController;
    searchController.delegate = searchResultsController;
    searchController.hidesNavigationBarDuringPresentation = NO;
    [self presentViewController:searchController animated:YES completion:nil];
}

@end

@implementation ArticleSearchViewController

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    ArticleDetailController * articleDetailController = [ArticleDetailController new];
   [(UINavigationController *)self.presentingViewController pushViewController:articleDetailController animated:YES];
}

@end

The push action happend below UISearchController.


Solution

  • You are presenting the search controller in wrong way. Look at part of the documentation.

    You use a search controller in tandem with your existing view controllers. When you have a view controller with searchable content, incorporate the search bar of a UISearchController object into your view controller’s interface. When the user interacts with that search bar, the search controller automatically displays a new view controller with the search results that you specify.

    Instead of this in your main controller:

    [self presentViewController:searchController animated:YES completion:nil]; 
    

    You should do this on iOS 11:

    self.definesPresentationContext = YES;
    self.navigationItem.searchController = searchController;
    

    Or this on pre iOS 11:

    self.definesPresentationContext = YES;
    self.navigationItem.titleView = searchController.searchBar;
    

    Or place anywhere else the searchController.searchBar in your presented view hierarchy.

    You should also setup the search controller in a place like viewDidLoad and not on a button press.

    And the way you are getting a reference to your navigationController in ArticleSearchViewController has to be updated to something like:

    [self.presentingViewController.navigationController pushViewController:articleDetailController animated:YES];
    

    View controller with searchable content:

    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self.view setBackgroundColor:[UIColor blackColor]];
    
        UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        ArticleSearchViewController *searchResultsController = [sb instantiateViewControllerWithIdentifier:@"ArticleSearchViewController"];
        UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
        searchController.searchResultsUpdater = searchResultsController;
        searchController.searchBar.delegate = searchResultsController;
        searchController.delegate = searchResultsController;
        searchController.hidesNavigationBarDuringPresentation = NO;
    //    [self presentViewController:searchController animated:YES completion:nil]; //WRONG
        self.definesPresentationContext = YES;
        self.navigationItem.searchController = searchController;
    }
    
    @end
    

    Results Controller:

    @implementation ArticleSearchViewController
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        UIViewController * articleDetailController = [UIViewController new];
        [self.presentingViewController.navigationController pushViewController:articleDetailController animated:YES];
    }
    
    - (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
        // update appropriately
    }
    
    @end