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

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.

Related

swift table view is locked when searchbar active

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
}

search result not work went add tableviewcell

Search bar is woking very well until I add custom tableview cell. It breaks when I search a keyword matching with a array. When I search wrong, it doesn't break.
var filteredArray = [String]()
var searchController = UISearchController()
var result = UITableViewController()
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: result)
tableView.tableHeaderView = searchController.searchBar
searchController.searchResultsUpdater = self
result.tableView.delegate = self
result.tableView.dataSource = self
result.tableView.register(UITableView.self, forCellReuseIdentifier: "Cell")
}
//config seachbar
func updateSearchResults(for searchController: UISearchController) {
filteredArray = array.filter( { (array : String) -> Bool in
if array.contains(searchController.searchBar.text!)
{
return true
}
else
{
return false
}
})
result.tableView.reloadData()
}
and this is a tableview cellForRow
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! SanPhamTableViewCell
// fill data into cell
if tableView == result.tableView
{
cell.name.text = filteredArray[indexPath.row]
cell.img.image = UIImage(named: ArrayImage[indexPath.row])
cell.price.text = ArrayPrice[indexPath.row]
cell.price.isUserInteractionEnabled = false
cell.desc.text = arrayDesc[indexPath.row]
cell.desc.isUserInteractionEnabled = false
}
else
{
cell.name.text = arrayName[indexPath.row]
cell.img.image = UIImage(named: arrayImage[indexPath.row])
cell.price.text = arrayPrice[indexPath.row]
cell.price.isUserInteractionEnabled = false
cell.desc.text = arrayDesc[indexPath.row]
cell.desc.isUserInteractionEnabled = false }
return cell
}
You need to register the cell like this in viewDidLoad, replace:
result.tableView.register(UITableView.self, forCellReuseIdentifier: "Cell")
with:
result.tableView.register(SanPhamTableViewCell.self, forCellReuseIdentifier: "Cell")
//
Edit : for xib
result.tableView.register(UINib(nibName: "SanPhamTableViewCell", bundle: nil), forCellReuseIdentifier: Cell)
I am not sure how are you making the SanPhamTableViewCell, But if you are using a custom nib then that nib must also be registered with tableView
result.tableView.register(UINib(nibName: "SanPhamTableViewCell", bundle: nil), forCellWithReuseIdentifier: "Cell")

Search Controller no results (blank page)

The basic table shows the results correctly - it work properly.
I have a problem with a table that shows the search results, always returns a white page. (no results) The problem may be two tables in one controller?
What am I doing wrong?
class SearchMagazineViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {
#IBOutlet var tableView: UITableView!
var resultsController: UITableViewController!
var searchController: UISearchController!
var searchMagazines: [Magazine]?
var latestPub = [Magazine]()
func updateSearchResults(for searchController: UISearchController) {
let searchText = searchController.searchBar.text!
if searchText.count > 0 {
self.searchMagazines = CoreDataHandler.searchMagazine(query: searchText, scope: 0)
}
self.resultsController.tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
latestPub = CoreDataHandler.latestMagazines() ?? [Magazine]()
resultsController = UITableViewController(style: .plain)
resultsController.tableView.register(UINib(nibName: "searchCell", bundle: nil), forCellReuseIdentifier: "searchCell")
resultsController.tableView.dataSource = self
resultsController.tableView.delegate = self
searchController = UISearchController(searchResultsController: resultsController)
searchController.delegate = self
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = true
navigationItem.searchController = searchController
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.resultsController {
return searchMagazines?.count ?? 0
}else{
return latestPub.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == self.resultsController {
let cell = tableView.dequeueReusableCell(withIdentifier: "searchCell", for: indexPath) as! SearchCell
let item = searchMagazines![indexPath.row]
cell.cat.text = TitleReturn(id: item.cat)
return cell
}else{
guard let cell = tableView.dequeueReusableCell(withIdentifier: "SearchCell") as? SearchTableViewCell else { return UITableViewCell() }
cell.title.text = latestPub[indexPath.row].title
return cell
}
}
}

Unable to segue to VC without dismissing SearchController

I'm unable to transition to my View Controller without having dismissed my Search Controller. My search controller is embedded in my TableView Header.
Is there a way of transitioning without having dismissed my Search Controller first?
Here is some code:
class ViewProfileViewController: UIViewController, UITableViewDelegate,
UITableViewDataSource, UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource, UISearchBarDelegate, UISearchResultsUpdating {
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.sizeToFit()
searchController.searchBar.searchBarStyle = .minimal
searchController.searchBar.placeholder = "Search City"
searchController.searchBar.showsCancelButton = true
searchController.searchBar.delegate = self
searchController.searchBar.backgroundColor = UIColor.white
self.myTable.tableHeaderView = searchController.searchBar
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath:
IndexPath) {
// Get rid of searchController
searchController.searchBar.endEditing(true)
searchController.isActive = false
searchController.dismiss(animated: true) { /* */ }
// Deselect row
tableView.deselectRow(at: indexPath, animated: true)
// Present your VC here
let mViewController = MController()
let navController = UINavigationController(rootViewController:
mViewController)
present(navController,animated: true, completion: nil)
}
}

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