3

so I previously had my search controller embedded inside the Navigation bar so that the gradient of the navigation bar also covered the search bar.

Suddenly, I believe from an XCode update, I found that now the navigation bar's background color stops firmly at the top of the search controller.I am having trouble pin-pointing why this happens.

This is my current code, which previously worked. Any thoughts?

private func setNavigationBarAesthetics() {

    if let navigationBar = self.navigationController?.navigationBar {

        navigationBar.setBackgroundImage(UIImage(named: "testbg"), for: .default)


    }

    self.searchController.searchBar.delegate = self
    self.searchController.delegate = self
    searchController.searchResultsUpdater = self
    searchController.definesPresentationContext = false
    searchController.obscuresBackgroundDuringPresentation = false

    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = true

    searchController.hidesNavigationBarDuringPresentation = false
}

enter image description here

degenPenguin
  • 725
  • 1
  • 8
  • 23
  • "it suddenly changed" What does that mean? – matt Oct 04 '19 at 17:06
  • 1
    XCode update I suspect. – degenPenguin Oct 04 '19 at 17:06
  • OK but you are not explaining what the problem is. Saying "changed" or "pinpoint the issue" does not tell us what the issue _is_. – matt Oct 04 '19 at 17:07
  • Oh, I need the blue gradient to encompass, the entire search bar. I'll clarify that, apologies – degenPenguin Oct 04 '19 at 17:07
  • 1
    OK so where does the gradient come from? Give us enough code to allow us to _reproduce the problem_ ourselves. – matt Oct 04 '19 at 17:08
  • Updated the original question – degenPenguin Oct 04 '19 at 17:12
  • OK so you're doing this wrong. Make the gradient the background image of the nav bar. (In iOS 13 you would use the UIBarAppearance to do that. But even in iOS 12 what you're doing is a totally wrong hack; they hand you this functionality, you should use what they've given you.) – matt Oct 04 '19 at 17:13
  • Unable to find any further links on how to do this. This link shows how to insert a `CAGradientLayer` into the `view.sublayer` , which is giving me the same result as what I already have https://stackoverflow.com/questions/24380535/how-to-apply-gradient-to-background-view-of-ios-swift-app – degenPenguin Oct 04 '19 at 17:34
  • @matt using this link to implement your suggestion, the gradient still stops above the search controller https://spin.atomicobject.com/2018/06/21/resize-navbar-gradient-ios/ – degenPenguin Oct 04 '19 at 17:39
  • But hacking with the search bar. Just set the navigation bar appearance's background image to the gradient image and stop. – matt Oct 05 '19 at 14:33

2 Answers2

3

There are two problems with that code. First, stop hacking the search bar:

self.searchController.searchBar.barTintColor = UIColor.clear // no
self.searchController.searchBar.backgroundImage = UIImage() // no
searchController.searchBar.backgroundColor = UIColor.clear // no
searchController.searchBar.barStyle = .blackTranslucent // no

Second, stop hacking the navigation bar: Delete the GradientView entirely from your code.

class GradientView: UIView { // no

Just use the tools that the framework gives you. Set the navigation bar's background image (to an image of a gradient) and stop. The search controller's search bar will automatically integrate itself correctly into the navigation bar:

enter image description here

EDIT Okay, so it turns out that this is issue is iOS 13 only. That's because what you're doing is not how to add a background image to a navigation bar in iOS 13. You will have to bifurcate your code:

    if #available(iOS 13.0, *) {
        let app = UINavigationBarAppearance()
        app.backgroundImage = im // the gradient image
        self.navigationController?.navigationBar.scrollEdgeAppearance = app
        self.navigationController?.navigationBar.standardAppearance = app
    } else {
        // your old code goes here
    }
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I followed your post and it simplified my coding. But it doesn't change the outcome. What does your code look like for that picture? – degenPenguin Oct 07 '19 at 15:09
  • Hi @markocalvocruz I told you what I do. I set the navigation bar's background image to an image of a gradient, and I set the navigation item's `searchController` to my UISearchController. That's all (except for making the rounded-rect background white). No trickery. – matt Oct 07 '19 at 15:13
  • The VC is 100% embedded inside a Navigation Controller in the Storyboard. I just updated my question to reflect all of the code changes according to your answer – degenPenguin Oct 07 '19 at 15:28
  • Still full of wrong hacks. Delete `navigationBar.isTranslucent = true`. Delete `navigationBar.barTintColor = UIColor.clear`. Delete all the stuff about the image bounds. Just do what I said and _no more_. – matt Oct 07 '19 at 15:31
  • Also take out the `if let textField = ...` stuff. Just do _only what I said_. Prove to yourself that it works. Then you can start playing around if you just can't live without hacking. – matt Oct 07 '19 at 15:36
  • Updated the question to reflect your suggestions. Unsure how I'd change the gradient function without bounds – degenPenguin Oct 07 '19 at 15:45
  • Well, use _any_ image as a test, just to prove to yourself that this normally just works. Don't worry about the size of the image. A solid color 100x100 image will do. – matt Oct 07 '19 at 15:49
  • Yup! This is the issue - the navigation bar's background image does not extend to the search bar, see my updated question – degenPenguin Oct 07 '19 at 15:52
  • Is this iOS 13? – matt Oct 07 '19 at 16:01
  • target deployment iOS 11.0, but I believe the problem started with an XCode update. It used to work even with my old hacky code – degenPenguin Oct 07 '19 at 16:14
  • I didn't ask what the target deployment was. I asked what _this_ is. What system are we actually running on when you see the problem? – matt Oct 07 '19 at 16:20
  • Ah! Yes the simulator is running iOS 13.0! – degenPenguin Oct 07 '19 at 16:21
  • 1
    Okay. So, what you're doing is not how to set the background image in iOS 13. You'll need to use `available` blocks to bifurcate your code. I'll post iOS 13 code for setting the background image. – matt Oct 07 '19 at 16:29
  • awesome! The new code fixed it. Thank you so much, I appreciate your patience – degenPenguin Oct 07 '19 at 16:42
  • No problem! Sorry it took so long to narrow it down. – matt Oct 07 '19 at 16:46
  • Do we know the code for fixing the gradient on iOS 11 & 12? This fixed iOS13 but broke it on older versions – degenPenguin Oct 29 '19 at 05:43
  • You said “This is my current code, which previously worked”. So you keep using it on iOS 11 and 12, as I said in my answer. – matt Oct 29 '19 at 11:01
  • My previous code was a gradient view that everybody told me to delete, which I did. I now set the gradient with `navigationBar.setBackgroundImage` but the gradient does not extend to the searchbar, like the picture in the question – degenPenguin Oct 30 '19 at 04:05
  • 1
    Well fine. But _this_ question was about iOS 13. I answered that. The end. If you now have a different question, ask a new question. – matt Oct 30 '19 at 11:52
  • @matt How did you manage below ios13? I set images navigationController?.navigationBar.setBackgroundImage(img, for: .default) but it doesn't work at all – zramled Nov 09 '20 at 09:17
  • @zramled It's the OP who was "managing below iOS 13", and the OP's question does not show that code. My answer is about iOS 13 and later, because that is what the question was. – matt Nov 09 '20 at 15:00
  • @matt I figure it out and I just updated my answer. thanks :) – zramled Nov 09 '20 at 23:06
2

Swift 5 that handle ios 12 and 13.

This is based from the answer with matt.

 if #available(iOS 13.0, *) {
        let app = UINavigationBarAppearance()
        app.backgroundImage = UIImage(named: "img")
        self.navigationController?.navigationBar.scrollEdgeAppearance = app
        self.navigationController?.navigationBar.standardAppearance = app
    } else {
       // iOS 12 to below
       if let navigationbar = self.navigationController?.navigationBar {
       navigationbar.barTintColor = UIColor(patternImage: UIImage(named: "img")!)
       navigationbar.isTranslucent = false
    }
   }
zramled
  • 331
  • 1
  • 3
  • 11