iOS 9 searchBar disappears from table header view when UISearchController is active
Asked Answered
M

13

55

The structure:

View1 (click a button) -> present modally (MyModalView: UITableViewController)

MyModalView has UISearchController embedded. The searchBar of UISearchController is placed in MyModalView.tableView.tableHeaderView.

It's been working fine since iOS 8.0. However on iOS 9, the searchBar disappear when the UISearchController is active. Please take a look at theses pictures below

The modal view:modal view

UISearchController active on iOS 8:search bar in iOS 8

UISearchController active on iOS 9:search bar in iOS 9

The very standard code:

override func viewDidLoad() {
    super.viewDidLoad()

    // Dynamically create a search controller using anonymous function
    self.resultSearchController = ({
        let controller = UISearchController(searchResultsController: nil)
        controller.searchResultsUpdater = self
        controller.dimsBackgroundDuringPresentation = false

        controller.searchBar.sizeToFit()
        controller.searchBar.delegate = self

        self.tableView.tableHeaderView = controller.searchBar

        return controller
    })()

    // Auto sizing row & cell height
    self.tableView.estimatedRowHeight = 130
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.definesPresentationContext = true

    // No footer for better presentation
    self.tableView.tableFooterView = UIView.init(frame: CGRectZero)
}

This issue also happens in iOS 9.1 beta...

Any idea / pointer would be deeply appreciated

Cheers.

Mordred answered 21/9, 2015 at 4:13 Comment(4)
For me, this only happens on the device (not in Simulator).Spikes
Hi @IanDundas I posted my answer below would you want to try it to see if it'll fix your problem?Mordred
yes, actually @Shwethascar's fixes it lucky - thanks though. Just adding some context for others, that it only happens for me on the actual device.Spikes
Try searchController.hidesNavigationBarDuringPresentation = falsePeeved
M
66

It seems all of us got the same problem but they were solved in different ways. However none of the suggested answers worked for me :(. Nevertheless thank you all for your time.

I got a solution that solved my problem. It is setting Extend Edges - Under Opaque Bars of my (MyModalView: UITableViewController) to true in the Storyboard using Interface Builder.

In summary:

MyModalView: UITableViewController, in Storyboard using Interface Builder has

Extend Edges: - Under Top Bars ticked - Under Bottom Bars ticked - Under Opaque Bars ticked

screenshot

Mordred answered 11/10, 2015 at 11:48 Comment(3)
Yep. Extend Edges: - Under Opaque Bars ticked in Storyboard did the trick.Prop
This has been plaguing me for hours. Thank you so much.Cartilaginous
Which properties do these checkboxes correspond to? Many people don't use Interface Builder.Scoop
D
70

I'm not sure what exactly is the problem but I 'fixed' it by:

self.searchController.hidesNavigationBarDuringPresentation = NO;
self.definesPresentationContext = NO;

My guess is that UISearchController is doing something funky when it is trying to present as a navigation bar. So, this is a hack but it at least doesn't block the user. The search bar doesn't do the cool animation and cover up the navigation bar.

Donau answered 21/9, 2015 at 18:52 Comment(6)
Only needed the first line searchController.hidesNavigationBarDuringPresentation = false (swift)Mercedezmerceer
Yes, Only need searchController.hidesNavigationBarDuringPresentation = false, That's real solution.Peeved
NO,not a real solution .Wht if we need to hide navigation bar and SearchBar is hidden under statusbar..?Chintz
I needed both theseTryparsamide
This should be the accepted answer. This is the only thing that worked for me. Thanks.Gulch
This is still the only answer I've found that fixes my problem. Agreed with above comments that the first part was sufficient.Tortuga
M
66

It seems all of us got the same problem but they were solved in different ways. However none of the suggested answers worked for me :(. Nevertheless thank you all for your time.

I got a solution that solved my problem. It is setting Extend Edges - Under Opaque Bars of my (MyModalView: UITableViewController) to true in the Storyboard using Interface Builder.

In summary:

MyModalView: UITableViewController, in Storyboard using Interface Builder has

Extend Edges: - Under Top Bars ticked - Under Bottom Bars ticked - Under Opaque Bars ticked

screenshot

Mordred answered 11/10, 2015 at 11:48 Comment(3)
Yep. Extend Edges: - Under Opaque Bars ticked in Storyboard did the trick.Prop
This has been plaguing me for hours. Thank you so much.Cartilaginous
Which properties do these checkboxes correspond to? Many people don't use Interface Builder.Scoop
C
36

I found it's the simulated metrics (top bar) in storyboard that's cause this problem. In my case, the following lines work, but I still don't know why.

- (void)willPresentSearchController:(UISearchController *)searchController {
    // do something before the search controller is presented
    self.navigationController.navigationBar.translucent = YES;
}

-(void)willDismissSearchController:(UISearchController *)searchController
{
    self.navigationController.navigationBar.translucent = NO;
}
Caddish answered 22/9, 2015 at 14:34 Comment(5)
it happens even with pure code . I bet that translucent = false actually removes a view or something instead of disabling the translucent effect hence the search bar simply goes beyond the visible areaWit
don't forget to set the searchController delegate to the class implementing these methods (usually self)Corps
This was the solution that made it work for me! Thanks!Rasla
searchController.searchBar.searchBarStyle = .default in willPresent and .minimal in willDismiss helped for me.Mallarme
Solved our issue as well - in our case the navigationBar overlaps the searchBar - setting translucent to on / off during inside the delegates fixed the issue.Religionism
W
19

I had to

self.aNavigationController?.extendedLayoutIncludesOpaqueBars = true

I found a similar question here but in my case it was not on the viewDidLoad method. I had to try different views until it worked. Now I can have both a custom navigation bar color and the search bar,

Wit answered 14/10, 2015 at 1:28 Comment(2)
Great Answer Jigzat !Sulphur
This should be added along with @David Trang answer.Pneumoconiosis
B
10

Thanks @wiles duan and @Techprimate

In my case, I fixed this issue by setting:

self.definesPresentationContext = NO;

And implement the following 2 methods in UISearchControllerDelegate

- (void)willPresentSearchController:(UISearchController *)searchController {
    // do something before the search controller is presented
    self.navigationController.navigationBar.translucent = YES;
}

-(void)willDismissSearchController:(UISearchController *)searchController
{
    self.navigationController.navigationBar.translucent = NO;
}
Brooks answered 13/1, 2016 at 2:53 Comment(1)
I fixed mine by just implementing the delegate methodsRafiq
V
6

I fixed it in my case by removing

definesPresentationContext = true

I didn't test yet if there are any disadvantages of removing this!

Volcanic answered 21/9, 2015 at 16:23 Comment(1)
Adding this fixed it for me. 😊Genie
Q
3

I had the same problem, and when I debugged the UI on Xcode I found that the UISearchBar view was moved to another view and the width was zeroed.

I fixed it by setting definesPresentationContext property of the UISearchController to false, and setting it true for the containing UITableViewController.

I added only one line to your viewDidLoad().

override func viewDidLoad() {
    super.viewDidLoad()

    // Dynamically create a search controller using anonymous function
    self.resultSearchController = ({
        let controller = UISearchController(searchResultsController: nil)
        controller.searchResultsUpdater = self
        controller.dimsBackgroundDuringPresentation = false
        controller.definesPresentationContext = false    // Disable the presentation controller

        controller.searchBar.sizeToFit()
        controller.searchBar.delegate = self

        self.tableView.tableHeaderView = controller.searchBar

        return controller
    })()

    // Auto sizing row & cell height
    self.tableView.estimatedRowHeight = 130
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.definesPresentationContext = true    // This one remains the same

    // No footer for better presentation
    self.tableView.tableFooterView = UIView.init(frame: CGRectZero)
}
Quilmes answered 15/6, 2017 at 5:57 Comment(0)
P
2

I don't have a navigation bar in this place of an app. None of other SO posts helped me, so I've fixed it this way:

- (void)layoutSubviews
{
    [[[self searchController] searchBar] sizeToFit];
}
Prototrophic answered 15/5, 2016 at 17:18 Comment(0)
N
1

Setting the navigationBar permanently to translucent in storyboard solved my problem.

Neilneila answered 22/9, 2015 at 19:12 Comment(0)
F
1

It works

override func viewDidLoad() {
    super.viewDidLoad()

    self.extendedLayoutIncludesOpaqueBars = !self.navigationController!.navigationBar.translucent
}
Finegrained answered 26/7, 2016 at 18:28 Comment(2)
I had to do this in viewDidAppear otherwise it breaks again somehow. Thanks @Apple.Chagres
This fixed it for me as well. ThanksImprecise
T
0

If you want to hide you navigation bar, and present search controller full screen, set the following on your navigation bar and search bar won't dissapper:

navigationController?.navigationBar.translucent = true
Twofold answered 14/4, 2016 at 15:25 Comment(0)
S
0
sc.hidesNavigationBarDuringPresentation = false

does the trick for me

lazy var searchController:UISearchController = {
        let sc = UISearchController(searchResultsController: nil)
        sc.searchResultsUpdater = self
        sc.obscuresBackgroundDuringPresentation = false
        sc.searchBar.placeholder = "Search"
        sc.hidesNavigationBarDuringPresentation = false
        return sc
    }()
Subulate answered 10/1, 2018 at 19:20 Comment(0)
L
0

None of them worked for me, I fixed it using this hack

func position(for bar: UIBarPositioning) -> UIBarPosition {
    if UIDevice.current.userInterfaceIdiom == .pad {
        return .top
    } else {
        if iOSVersion <= 9 {
            return .top
        }
        return .topAttached
    }


}
Leverett answered 20/6, 2018 at 6:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.