swift table view is locked when searchbar active - ios

i'm using a large navigation bar which includes a searchcontroller. If i dont search i can scroll through my tableview without problems, but if i'm searching it seams like its locked. Here is my code:
func updateSearchResults(for searchController: UISearchController) {
// First we will check if input is only containing numbers => search for PLZ otherwise we will check if a restaurant is called like this otherwise search if there is a suitable city
self.navigationItem.title = searchController.searchBar.text!
if !searchController.isActive{
//TODO get all restaurants for default city
self.navigationItem.title = "München"
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "partnerscell", for: indexPath) as! PartnersCellTableViewCell
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var bounds = UIScreen.main.bounds
var width = bounds.size.width
var height = bounds.size.height
return height/2.2
}
#IBOutlet weak var tv: UITableView!
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
}
self.navigationController?.navigationBar.isTranslucent = true
self.navigationItem.searchController = searchController
self.navigationController?.navigationBar.shadowImage = UIImage()
}
Also if i'm searching my toolbar looks darker. Please find attached two screenshots:

You can't access the table view, because there is an invisible layer over it caused by wrong configuration of UISearchController.
Modify the searchController this way:
let searchController = UISearchController(searchResultsController: nil)
searchController.obscuresBackgroundDuringPresentation = false
searchController.definesPresentationContext = true

You can not access tableview when your search is active because attribute of UISearchController obscuresBackgroundDuringPresentation is default true which indicating underlying content of controller is obscured when search is active. So you can set as follow:
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
}
self.navigationController?.navigationBar.isTranslucent = true
self.navigationItem.searchController = searchController
self.navigationController?.navigationBar.shadowImage = UIImage()
searchController.obscuresBackgroundDuringPresentation = false
searchController.definesPresentationContext = true
}

Related

How to display search results like the iOS "Contacts" app

I am new iOS programming. I have tried to implement my app to look like the iOS Contacts app. But I have no idea how to implement what I desire. I want to get search results to look like the default iOS app.
Look what I tried so far:
When I type something the dimsBackgroundDuringPresentation is still true.
Here is my expectation:
I am wondering how this app shows results like this.
Here is how i declared UISearchController
lazy var searchController: UISearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.hidesNavigationBarDuringPresentation = false
controller.searchBar.sizeToFit()
controller.searchBar.backgroundColor = UIColor.clear
controller.searchBar.placeholder = "Search"
controller.dimsBackgroundDuringPresentation = true
return controller
})()
Here is how i initialized searchBar to header section of tableView
let searchBar = searchController.searchBar
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
searchBar.delegate = self
tableView.tableHeaderView = searchController.searchBar
Here is function for delegate UISearchResultsUpdating
func updateSearchResults(for searchController: UISearchController) {
if let count = searchController.searchBar.text?.count {
if count > 0 {
filterArray.removeAll(keepingCapacity: false)
var a = [String]()
a = [searchController.searchBar.text!]
filterArray = a
searchController.dimsBackgroundDuringPresentation = false
tableView.reloadData()
}else {
searchController.dimsBackgroundDuringPresentation = true
filterArray.removeAll(keepingCapacity: false)
filterArray = array
tableView.reloadData()
}
}
}
Here is my tableView cell looks like
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive {
return filterArray.count
}else {
return array.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
if searchController.isActive {
cell.textLabel?.text = filterArray[indexPath.row]
}else {
cell.textLabel?.text = array[indexPath.row]
}
return cell
}
Try with these options:
let search = UISearchController(searchResultsController: nil)
self.definesPresentationContext = true
search.dimsBackgroundDuringPresentation = false
navigationItem.searchController = search
navigationItem.hidesSearchBarWhenScrolling = false
Try the code in my repo to see it working just tap a tableview item and it will segue to the second controller where you can see the searchbar and tap it to see if this is what you wanted
github link
if navigationItem.searchController == nil {
if searchController == nil {
searchController = UISearchController(searchResultsController: nil)
searchController?.searchBar.placeholder = "Search"
searchController?.delegate = self
searchController?.searchResultsUpdater = self
searchController?.dimsBackgroundDuringPresentation = false
searchController?.searchBar.searchBarStyle = .minimal
}
self.navigationItem.searchController = searchController
self.navigationItem.hidesSearchBarWhenScrolling = false
}
Use property hidesSearchBarWhenScrolling to make the search bar not scroll up, like the contacts app.

How to hide searchBar under navigation bar and show it when user pull the tableView down?

in my app I want to implement searchBar above the tableView which will hide under navigationBar. when user pull the tableView down then I want to show the searchBar. Please tell me how I can achieve this in swift. Thanks!!
enter image description here
Set up rootViewController with UINavigationController in AppDelegate.swift.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = UINavigationController(rootViewController: ViewController())
return true
}
Then in ViewController.swift, add TableView by properly implementing UITableViewDataSource and UITableViewDelegate methods.
Then, declare UISearchController and add it to tableHeaderView instead of adding as subview. Then, set the content offset of tableView so that by default the searchController is hidden. When tableView is scrolled down, then only searchBar is shown.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private var myData: NSArray = ["One", "Two", "Three"]
private var tableView: UITableView!
//lazy var searchBar:UISearchBar = UISearchBar()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
navigationItem.title = "Home"
tableView = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
tableView.dataSource = self
tableView.delegate = self
self.tableView.backgroundColor = .brown
let searchBarController: UISearchController = UISearchController(searchResultsController: nil)
tableView.tableHeaderView = searchBarController.searchBar
tableView.setContentOffset(CGPoint.init(x: 0, y: 44), animated: false)
self.view.addSubview(tableView)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("\(indexPath.row)")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath)
cell.textLabel?.text = myData[indexPath.row] as! String
cell.backgroundColor = .brown
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Initially when the application is first launched searchBar is hidden, only tableView is displayed:
After tableView is scrolled down, then searchBar appears:
Simply make the table view or collection view scroll to the first row right after setting the search controller.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.searchController = searchController
tableView.scrollToRow(
at: .init(row: 0, section: 0),
at: [.bottom, .left],
animated: false
)
}
I could hide the searchBar with this code
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
self.searchbar()
self.automaticallyAdjustsScrollViewInsets = false
tableView.contentInset = UIEdgeInsets.zero
tableView.tableHeaderView = searchController.searchBar
//Hide SearchBar
tableView.setContentOffset(CGPoint.init(x: 0, y: 44), animated: false)
}
func searchbar() {
searchController.searchResultsUpdater = self as UISearchResultsUpdating
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
}
To initially hide the searchBar, simply set the navigationItem.searchController property after your table view (or collection view) has been populated with data.

Search Bar Glitch

The problem:
Instead of adding a search bar(with a search and results controller) to a table view controller, I have added it to a regular view controller's navigation bar. At first everything seems fine, but when I click on the search bar the screen turns gray.
This is my code:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchResultsUpdating, UISearchBarDelegate{
var schools = ["Saratoga", "Fremont", "Argonaut", "Redwood", "Foothill", "Miller", "Rolling Hills"].sorted()
var filteredSchools = ["Saratoga", "Fremont", "Argonaut", "Redwood", "Foothill", "Miller", "Rolling Hills"].sorted()
var searchController: UISearchController!
var resultsController: UITableViewController!
override func viewDidLoad() {
super.viewDidLoad()
resultsController = UITableViewController()
searchController = UISearchController(searchResultsController: resultsController)
resultsController.tableView.delegate = self
resultsController.tableView.dataSource = self
searchController.searchResultsUpdater = self
self.view.addSubview(searchController.searchBar)
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: searchController.searchBar)
}
func updateSearchResults(for searchController: UISearchController) {
let currText = searchController.searchBar.text ?? ""
filteredSchools = schools.filter({ (school) -> Bool in
if school.contains(currText){
return true
}
return false
})
resultsController.tableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredSchools.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = filteredSchools[indexPath.row]
return cell
}
}
Add these lines in viewDidLoad:
resultsController.tableView.backgroundColor = UIColor.clear
searchController.hidesNavigationBarDuringPresentation = false
Your Navigation Bar is hiding that's all.
If you don't want the gray tint:
searchController.dimsBackgroundDuringPresentation = false

why added blank space between searchBar and tableview?

I have a tableview controller. I added searchBar. But when i click on searchBar, i have a blank space between searchBar and TableView? Why? And how it fix?
In down i add screenshot and listing of code tableViewController. Thanks for help.
!!!!!! - LISTING TableViewController - !!!!!!
class AlfavitController: UITableViewController, UISearchResultsUpdating {
var searchController : UISearchController!
var resultController = UITableViewController()
override func viewDidLoad() {
super.viewDidLoad()
self.downloadData(param: Manager.id)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.searchController = UISearchController(searchResultsController: self.resultController)
self.tableView.tableHeaderView = self.searchController.searchBar
self.searchController.searchResultsUpdater = self
self.resultController.tableView.dataSource = self
self.resultController.tableView.delegate = self
definesPresentationContext = true
}
func updateSearchResults(for searchController: UISearchController) {
self.arFiltLet = self.arWords.filter{(lett : String) -> Bool in
if lett.lowercased().contains(self.searchController.searchBar.text!.lowercased()){
return true
}else{
return false
}
}
self.resultController.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.tableView {
return self.arWords.count
}else{
return self.arFiltLet.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if tableView == self.tableView{
cell.textLabel?.text = self.arWords[indexPath.row]
}else{
cell.textLabel?.text = self.arFiltLet[indexPath.row]
}
return cell
}
The reason this happens is UIViewController’s property automaticallyAdjustsScrollViewInsets, which is a Boolean value that indicates whether the view controller should automatically adjust its scroll view insets., and defaults to YES.
Solution:-
Either write below code in your viewDidLoad():
automaticallyAdjustsScrollViewInsets = false
Or set it through storyboard/XIB whichever you use:

UISearchController searchbar animation very slow first time

In iOS 9 I am using UISearchController and displaying its search bar within a UIViewController, I am experiencing a lot of lag the first time I click on the search bar and have tried everything i can think of to no avail...below is my code along with a link to a video of the lag happening - the lag happens on both the simulator and my device.
func setupUI() {
self.view.backgroundColor = UIColor.whiteColor()
// Required to properly display searchbar within nav & tabbar controllers
self.extendedLayoutIncludesOpaqueBars = true // have tried setting this to false as well
self.definesPresentationContext = true
self.searchResultsController = AppDelegate.getViewController(ScheduleStoryboard.name, controllerName: ScheduleStoryboard.Identifiers.foodSearchResults) as? SearchResultsController
self.searchController = UISearchController(searchResultsController: searchResultsController)
self.searchController.searchResultsUpdater = self
self.searchController.delegate = self
self.searchController.dimsBackgroundDuringPresentation = true
self.searchController.searchBar.delegate = self
self.searchController.searchBar.placeholder = "Search foods..."
self.searchController.searchBar.setBackgroundImage(UIImage(named: "background-searchbar")?.resizableImageWithCapInsets(UIEdgeInsetsMake(0, 0, 0, 0)), forBarPosition: .Any, barMetrics: .Default)
self.searchController.searchBar.tintColor = UIColor.whiteColor()
self.searchController.searchBar.sizeToFit()
// this headerView does NOT belong to the tableView, its anchored on top of the tableView so that the searchbar remains fixed when scrolling
self.headerView.addSubview(searchController.searchBar)
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.tableHeaderView?.backgroundColor = UIColor.clearColor()
self.tableView.tableHeaderView?.addBorder(.Bottom, color: UIColor.groupTableViewBackgroundColor(), width: 0.25)
self.segmentedControl.tintColor = UIColor.genioBlue()
}
Here is a link to the video showing whats happening: http://sendvid.com/xgq81stx
Thanks!
I've only ever created a search controller once, but I used a UITableViewController as my base class. Here is my implementation:
class SearchController: UITableViewController {
let searchController = UISearchController(searchResultsController: nil)
var items:[ArrayOfYourType]
var filteredItems:[ArrayOfYourType]
var scopeTitles:[String]?
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
searchController.searchBar.scopeButtonTitles = scopeTitles
searchController.searchBar.delegate = self
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.active {
return filteredItems.count
}
return items.count
}
func filterContentForSearchText(searchText: String, scope: String = "All") {
filteredItems = items.filter { item in
//return true or false depending on your filter
return true
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle,
reuseIdentifier: nil)
let item: String
let category: String
if searchController.active {
item = filteredItems[indexPath.row].getTitle()
category = filteredItems[indexPath.row].getCategory()
}
else {
item = items[indexPath.row].getTitle()
category = items[indexPath.row].getCategory()
}
cell.textLabel?.text = item
cell.detailTextLabel?.text = category
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//your code here
}
}
//MARK: UISearchResultsUpdating
extension SearchController: UISearchResultsUpdating {
func updateSearchResultsForSearchController(searchController: UISearchController) {
if let _ = scopeTitles {
let searchBar = searchController.searchBar
let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
filterContentForSearchText(searchController.searchBar.text!,scope:scope)
}
else {
filterContentForSearchText(searchController.searchBar.text!)
}
}
}
//MARK: UISearchBarDelegate
extension SearchController: UISearchBarDelegate {
func searchBar(searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
filterContentForSearchText(searchBar.text!, scope: searchBar.scopeButtonTitles![selectedScope])
}
}
I hope this helps :)
Could it be possible that the image you are using for the background search bar is too large?
It might be quicker to create a gradient. Here is a good tutorial

Resources