Swift 4 - iOS 11 Search bar scope won't appear as it should
Asked Answered
C

4

3

I have an app which works nice and without any problems on iOS 10 but with iOS 11 and Xcode Beta 5, I have this strange problem with search bar scope where the scope bar seems like it was cut from the bottom. (It was the same with all versions of Xcode beta and iOS 11) I would really really be glad if someone can put me in the right direction. Thanks

Initial Screen

Above you can see what I see when I press the hamburger menu button. No problem here.. searchbar also has a scopebar which shows up when clicked on.I did not set it to show up programatically.But I guess this is its default behaviour when scope button titles are set.

The Problem:

problem

When I click on the searchbar to enter information I see the screen above. On iOS 10 I had no problems. But now, with iOS 11, whatever I do I just cannot make it work like it works on iOS 10. Search scope bar shows up like it was cut from the bottom.

This is how it shows up in iOS 10 and I want it to be in iOS 11.

workingInIOS10

Storyboard view of the screen

storyboard view of the screen

I am pasting the relevant code here.

    class SlideMenuViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UISearchControllerDelegate,UIGestureRecognizerDelegate{

     let searchController = UISearchController(searchResultsController: nil)

    @IBOutlet var sview: UIView!

    @IBOutlet var tableView: UITableView!



override func viewWillAppear(_ animated: Bool) {
//some non relevant code before this

 if sview.subviews .contains(searchController.searchBar) {
            print("Already contains")


        } else {

            sview.addSubview(searchController.searchBar)
            print(searchController.searchBar.showsScopeBar)

            searchController.searchBar.sizeToFit()
            searchController.searchBar.frame.size.width = view.frame.size.width



          searchController.searchBar.barTintColor = searchBarTintColor

            searchController.searchBar.tintColor = searchTintColor
        }



    }


override func viewDidLoad() {

//some other code

searchController.searchBar.delegate = self

searchController.searchBar.scopeButtonTitles = [NSLocalizedString("İsimlerde", comment: ""), NSLocalizedString("Açıklamalarda", comment: "")]

        searchController.searchBar.returnKeyType = UIReturnKeyType.done

searchController.searchResultsUpdater = self

        searchController.dimsBackgroundDuringPresentation = false
        definesPresentationContext = true

//some other code

}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

     if searchController.isActive && searchController.searchBar.text != "" {

        switch scpglobal {
            case NSLocalizedString("İsimlerde", comment: ""):
                return filteredIsimler.count

            case NSLocalizedString("Açıklamalarda", comment: ""):
                return filteredAciklamalar.count

            default:
                print("Tableview default")
        }

        }



        return isimlerArray.count
    }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

//some code about search here but nothing that will result in that behaviour

}

 func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        print("cancel")
        searchController.searchBar.text = ""

    }


func updateSearchResults(for searchController: UISearchController) {


        let searchBar = searchController.searchBar



        let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
        filterContentForSearchText(searchText: searchController.searchBar.text!, scope: scope)
        tableView.reloadData()
    }

}


extension SlideMenuViewController:UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
        filterContentForSearchText(searchText: searchController.searchBar.text!, scope: searchController.searchBar.scopeButtonTitles![selectedScope])
    }
}

Edit: This is what happens if I add constraints to search bar. First everything seems good.

withConstraints1st

Then when you click on search bar this happens..Search bar moves out of the screen. See the arrow.

withConstraints2nd

But if you close the sliding menu and re-open it then

withConstraints3rd

Everything works OK until you click the cancel button. After that you have to do all this again to see the search bar working.

Code for the constraints

 searchController.searchBar.translatesAutoresizingMaskIntoConstraints = false
 sview.addConstraint(NSLayoutConstraint(item: searchController.searchBar, attribute: .top, relatedBy: .equal, toItem: sview, attribute: .top, multiplier: 1, constant: 0))
 sview.addConstraint(NSLayoutConstraint(item: searchController.searchBar, attribute: .bottom, relatedBy: .equal, toItem: sview, attribute:.bottom, multiplier: 1, constant: 0))

 sview.addConstraint(NSLayoutConstraint(item: searchController.searchBar, attribute: .leading, relatedBy: .equal, toItem: sview, attribute: .leading,multiplier: 1, constant: 0))
 sview.addConstraint(NSLayoutConstraint(item: searchController.searchBar, attribute: .trailing, relatedBy: .equal, toItem: sview, attribute: .trailing, multiplier: 1, constant: 0))
Computerize answered 20/8, 2017 at 13:30 Comment(2)
Have you added constraints for Search bar?Kaveri
@ImadAli tried it..Same or worse results.Computerize
K
14

Check out this WWDC 2017 video.

You should do something like this:

if #available(iOS 11.0, *) {
    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = false
} else {
    tableView.tableHeaderView = searchController.searchBar
}

and then do the changes you need accordingly.

Koodoo answered 21/9, 2017 at 19:10 Comment(1)
navigationItem.searchController puts the search bar below the title.Apparel
C
4

I was able to resolve the issue by replacing searchController with a custom searchBar.

let searchBar = UISearchBar(frame:CGRect(x: 0, y: 0, width: 266, height: 100))

Be careful though, do not forget to use

searchBar.sizeToFit 

inside searchBarShouldBeginEditing and searchBarShouldEndEditing or else you might have strange UI problems especially if you are using the

searchBar.showsScopeBar = true

so, if you are having a similar problem, get rid of the searchController and implement a searchBar and its delegate methods. It will not give you the same scopeBar animation but at least it works. Another downside for this method is, if you have the searchBar.isTranslucent = true you might see the ghost of another scopeBar inside the searchBar. So make sure that

searchBar.isTranslucent = false

If anyone comes up with a better way to solve this problem, I am all ears...

Sample Delegate Setup

 func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
    searchBar.showsScopeBar = true
    searchBar.sizeToFit()
    searchBar.setShowsCancelButton(true, animated: true)
    return true
}

func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
    searchBar.showsScopeBar = false
    searchBar.sizeToFit()
    searchBar.setShowsCancelButton(false, animated: true)
    return true
}
Computerize answered 16/9, 2017 at 9:15 Comment(1)
searchBar.sizeToFit() is the clue for iOS11 issue with scopesCopyist
O
1

This might solve your problem:

func searchDisplayController(_ controller: UISearchController, willShowSearchResultsTableView tableView: UITableView)
 {
    tableView.backgroundColor = self.tableView.backgroundColor
    tableView.rowHeight = self.tableView.rowHeight
    tableView.tableFooterView = UIView()
}
Output answered 15/12, 2017 at 11:36 Comment(0)
H
0

I had a similar issue when my iOS was updated to the most recent version. The scope bar did not show up when the search bar was activated.

My solution is to add the following code in my configuration method:

private func configSearchControll() {
  let sc =  UISearchController(searchResultsController: nil)
  // config search controller
  if #available(iOS 16.0, *) {
        sc.scopeBarActivation = .onSearchActivation
    } else {
        if #available(iOS 13.0, *) {
            sc.automaticallyShowsScopeBar = true
        } else {
            // Fallback on earlier versions
        }
    }
}

With the above change, my scope items now appear when the search bar is activated and focused.

In my view controller's viewDidLoad event

override func viewDidLoad() {
  super.viewDidLoad()
  // configuration for the view 
  DispatchQueue.main.async {
        [weak self] in
        guard let this = self else { return }
        this.configSearchController()
    }
}

Reference: Apple Developer

Homicide answered 28/3, 2024 at 20:10 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.