9
votes

To make this short, I have a main view controller that has the navigation bar hidden, from that VC's navigation controller, I push another view controller which has the navigation bar visible. Then I add a searchController to the navigationItem to add the searchBar when I scroll down. Everything is working fine until you swipe back to pop the VC.

The navigation bar will animate leave the screen with the VC, but the searchBar will animate as if it's going up in place. What's worse is if I cancel the swipe to pop, the whole searchBar disappears and a black view appears instead (I think the searchController background ow whatever view background).

I tried everything, it's a few lines of code yet I've been pulling my hair to solve this. I know I can just disable swipe to pop but I don't want that(+ even when pressing back the searchBar animates in the same weird way) and I don't want to add a searchBar in any other way.

In the attached video I'm just swiping with my finger to show the animation.

desc

- (void)viewDidLoad {
    [super viewDidLoad];
    self.definesPresentationContext = YES;
    [self.navigationController setNavigationBarHidden:NO];

    if (@available(iOS 11.0, *)) {
        self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
        _searchController.delegate = self;
        _searchController.searchResultsUpdater = self;
        _searchController.searchBar.placeholder = @"Search";
        self.navigationItem.searchController = _searchController;
        self.navigationItem.hidesSearchBarWhenScrolling = YES;
    }
}
5
Show some code, how you add the search barScriptable
Sure, I edited the question to add the code.Eph Bee
Anyone? Anything?Eph Bee
Could you please share your project code?Harshal Wani
@HarshalWani i uploaded a sample project here: github.com/DanielKlink/SearchbarNavigationPopIssueKlinki

5 Answers

0
votes

Adding additional UISearchController is an overkill I believe. You can always add standalone UISearchbar to your view controller via storyboard or code, and make your searchbar-hosting view controller as the delegate of that searchbar.

Something like this:

    self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 0, NAVBAR_HEIGHT)];   
    self.searchBar.delegate = self;
    self.view.addSubView(self.searchBar);

This way, navigation item coupling with searchbar will go away, and hopefully the problem will be solved.

0
votes

Place the search bar in the navigation item's title view instead of assigning UISearchController to UINavigationItem's searchController

replace

navigationItem.searchController

with

navigationItem.titleView = searchController?.searchBar

UPDATED ANSWER:

Issue is due to the method used to hide NavigationBar There are different ways to hide NavigationBar

self.navigationController?.setNavigationBarHidden(false, animated: true)
self.navigationController?.navigationBar.isHidden = false
self.navigationController?.isNavigationBarHidden = false

And it seems you used setter only property to hide on MasterViewController

self.navigationController?.setNavigationBarHidden(true, animated: true)

Instead, use isNavigationBarHidden is both a setter and a getter.

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.isNavigationBarHidden = true
    }

override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.navigationController?.isNavigationBarHidden = false
    }

And also remove setNavigationBarHidden from DetailViewController

Cheers!

0
votes

I tried the answers here, but none of them didnt work as i wanted. The following solution worked for me.

For the wrong animation i did the following in the viewController with the searchBar:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    let containerView = transitionCoordinator?.containerView
    let currentPosition = self.navigationItem.searchController?.searchBar.superview?.frame.origin.x
    transitionCoordinator?.animateAlongsideTransition(in: containerView, animation: { (context) in
        if context.viewController(forKey: .to) is PreviousViewController {
            self.navigationItem.searchController?.searchBar.superview?.frame.origin.x = self.view.frame.size.width

        }

    }, completion: { (context) in
        self.navigationItem.searchController?.searchBar.superview?.frame.origin.x = currentPosition ?? 0
    })
}

For the disappearing of the searchBar i scrolled the tableView a bit which lets the searchBar appear back. The problem is that the searchBar is completly removed from its superView. But with this tiny scroll "animation" the searchbar is back again. Not realy cool but it worked:

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

    //workaround for showing the searchbar again if popgesture was canceled
    var offset = self.tableView.contentOffset
    offset.y -= 0.5
    UIView.animate(withDuration: 0.05, animations: {
        self.tableView.setContentOffset(offset, animated: false)
    }, completion: {_ in
        offset.y += 0.5
        self.tableView.setContentOffset(offset, animated: false)
    })
}
0
votes

I think this is iOS 11, 12 bug because it's working perfectly in iOS 13 beta 7.

0
votes

I've tried a lot to search for a solution to fix this issue, and I finally found this solution,

try using it:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationItem.hidesSearchBarWhenScrolling = false
}