I would like to add a search bar above my collection view and when press it will show like the video showing .https://www.youtube.com/watch?v=mgS2Pzy5eJk .Thanks.
You can directly use iOS default UISearchDisplayController as following tutorial:
UISearchDisplayController Tutorial
Read this tutorial and try it..
Hope it helps...
When the user click the searchBar:
remove or hide the NavigationBar
Adjust the auto layout constraint of search Bar accordingly.
Add animation as you want
Do these thing in func searchBarTextShouldBeginEditing(searchBar: UISearchBar)
func searchBarTextShouldBeginEditing(searchBar: UISearchBar) {
//remove or hide the NavigationBar
//update auto layout constraint
UIView.animateWithduration(0.3) {
self.view.layoutIfNeeded()
}
return true
}
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UISearchResultsUpdating {
#IBOutlet weak var tableview: UITableView!
let unfilteredNFLTeams = ["Bengals", "Ravens", "Browns", "Steelers", "Bears", "Lions", "Packers", "Vikings",
"Texans", "Colts", "Jaguars", "Titans", "Falcons", "Panthers", "Saints", "Buccaneers",
"Bills", "Dolphins", "Patriots", "Jets", "Cowboys", "Giants", "Eagles", "Redskins",
"Broncos", "Chiefs", "Raiders", "Chargers", "Cardinals", "Rams", "49ers", "Seahawks"].sorted()
var filteredNFLTeams: [String]?
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
filteredNFLTeams = unfilteredNFLTeams
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
tableview.tableHeaderView = searchController.searchBar
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let nflTeams = filteredNFLTeams else {
return 0
}
return nflTeams.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "nandhu", for: indexPath)
if let nflTeams = filteredNFLTeams {
let team = nflTeams[indexPath.row]
cell.textLabel!.text = team
}
return cell
}
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text, !searchText.isEmpty {
filteredNFLTeams = unfilteredNFLTeams.filter { team in
return team.lowercased().contains(searchText.lowercased())
}
} else {
filteredNFLTeams = unfilteredNFLTeams
}
tableview.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Related
I am trying to create a joke app. The search bar works. But when I select the search results, it won't take me to the tableview( the jokes). How can I fix it? Thanks everyone in advance.
import UIKit
class JokeTableViewController: UITableViewController, UISearchResultsUpdating {
var jokes = [ "chiken", "Walk into A Bar", "Olives", "Racer", "love"]
var filteredJokes = [String]()
var searchController : UISearchController!
var resultsController = UITableViewController()
override func viewDidLoad() {
super.viewDidLoad()
self.resultsController.tableView.dataSource = self
self.resultsController.tableView.delegate = self
self.searchController = UISearchController(searchResultsController: self.resultsController)
self.tableView.tableHeaderView = self.searchController.searchBar
self.searchController.searchResultsUpdater = self
//self.searchController.dimsBackgroundDuringPresentation = false
}
func updateSearchResults(for searchController: UISearchController) {
self.filteredJokes = self.jokes.filter { (jokee:String) -> Bool in
if jokee.lowercased().contains(self.searchController.searchBar.text!.lowercased()){
return true
}else {
return false
}
}
//Update the results TableView
self.resultsController.tableView.reloadData()
}
//WHEN SELECTED TO TO THE JOKES
// HOW MANY?
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.tableView{
return self.jokes.count
} else {
return self.filteredJokes.count
}
}
//WHAT GOES INSIDE?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
if tableView == self.tableView{
cell.textLabel?.text = self.jokes[indexPath.row]
} else{
cell.textLabel?.text = self.filteredJokes[indexPath.row]
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let selectedJoke = jokes[indexPath.row]
performSegue(withIdentifier: "moveToJokeDefinition", sender: selectedJoke)
}
override func prepare( for segue: UIStoryboardSegue, sender: Any?){
if let jokeVC = segue.destination as? JokeDefinitionViewController{
if let selectedJoke = sender as? String {
jokeVC.joke = selectedJoke
}
//select the jokes
}
}
}
You should use one global variable.
var globaldata = String
self.globaldata = self.jokes .... initData............
you should use this data in tableView Delegate functions.
While searching a tableView, every time I try to select a row it just takes me back to the unsearched tableView. What am I missing? the segue works perfectly when not filtering through the table. The ability to select a row just disapears while the searchBar is activated.
import UIKit
import Foundation
class BenchmarkWODViewController: UITableViewController, UISearchResultsUpdating {
var WodList = [WOD]()
var FilteredWodList = [WOD]()
var Keyword = ""
var searchController : UISearchController?
var index = Int()
#IBAction func backButton(sender: AnyObject) {
self.navigationController?.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
for wodData in BenchmarkWODs.library {
let wod = WOD(dictionary: wodData)
WodList.append(wod)
}
// Search Bar
self.searchController = UISearchController(searchResultsController: nil)
self.searchController?.searchBar.autocapitalizationType = .None
self.tableView.tableHeaderView = self.searchController?.searchBar
self.searchController?.searchResultsUpdater = self
self.Keyword = ""
definesPresentationContext = true
self.filterByName()
}
func filterByName(){
self.FilteredWodList = self.WodList.filter({ (wod: WOD) -> Bool in
if self.Keyword.characters.count == 0 {
return true
}
if (wod.name?.lowercaseString.rangeOfString(self.Keyword.lowercaseString)) != nil {
return true
}
return false
})
self.tableView.reloadData()
}
// Search Bar Function
func updateSearchResultsForSearchController(searchController: UISearchController) {
Keyword = searchController.searchBar.text!
self.filterByName()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.FilteredWodList.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("BenchmarkCell", forIndexPath: indexPath) as UITableViewCell
let wod = self.FilteredWodList[indexPath.row]
if let wodName = wod.name {
cell.textLabel?.text = wodName
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.filterByName()
self.performSegueWithIdentifier("showBenchmarkDetail", sender: nil)
}
}
Figured it out after playing around. Apparently adding the below code corrects the problem.
searchController?.dimsBackgroundDuringPresentation = false
swift 'dimsBackgroundDuringPresentation' was deprecated in iOS 12.0 Use the obscuresBackgroundDuringPresentation property instead.
searchController?.obscuresBackgroundDuringPresentation = false
searchController.obscureBAckgroundDuringPresentation = false is deprecated in IOS 12.0, so for me it was issue with other gesture detector added to the tableview , so make sure you dont have any other gesture detector and touchesview method that distort the normal working flow of tablview's delegate method( didSelectAtRow ), hope it will work,
I have implemented a simple UISearchController into my UITableViewController programatically. And below is my complete code:
import UIKit
class TableViewController: UITableViewController, UISearchResultsUpdating {
let appleProducts = ["Mac","iPhone","Apple Watch","iPad"]
var filteredAppleProducts = [String]()
var resultSearchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.searchBar.sizeToFit()
self.tableView.tableHeaderView = self.resultSearchController.searchBar
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 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 {
// #warning Incomplete implementation, return the number of rows
if (self.resultSearchController.active){
return self.filteredAppleProducts.count
}else{
return self.appleProducts.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell?
if (self.resultSearchController.active)
{
cell!.textLabel?.text = self.filteredAppleProducts[indexPath.row]
return cell!
}
else
{
cell!.textLabel?.text = self.appleProducts[indexPath.row]
return cell!
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("Detail") as! DetailViewController
self.navigationController!.pushViewController(vc, animated: true)
}
func updateSearchResultsForSearchController(searchController: UISearchController){
self.filteredAppleProducts.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (self.appleProducts as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredAppleProducts = array as! [String]
self.tableView.reloadData()
}
}
My resultSearchController is working completely fine but when I click on any cell then UISearchController is appearing into my next view too as shown into below image:
But my Second view is empty.
how I can remove this resultSearchController when I switch to another view so it will not appear into next view?
Project Sample for more Info.
Just add one line in viewDidLoad
self.definesPresentationContext = true
Doc
A Boolean value that indicates whether this view controller's view is covered when the view controller or one of its descendants presents a view controller.
GIF
I have a simple tableView, DailyAttendanceController, with a searchbar. Searchbar was added in its viewDidLoad. View TableView here.
import UIKit
class OldCellsTableViewController: UITableViewController {
let data = ["A", "B", "C"]
var searchController:UISearchController!
let resultsController = SearchResultsUpdater()
override func viewDidLoad() {
super.viewDidLoad()
resultsController.data = data
searchController = UISearchController(searchResultsController: resultsController)
let searchBar = self.searchController.searchBar
searchBar.scopeButtonTitles = ["All", "Short", "Long"]
searchBar.placeholder = "Search for a student"
searchBar.sizeToFit()
self.tableView.tableHeaderView = searchBar
self.searchController.searchResultsUpdater = resultsController
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let info = data[indexPath.row]
cell.textLabel?.text = info
return cell
}
}
I then created another class, SearchResultsController, to handle the search. Searching works fine, but space is allocated for DailyAttendanceController's header. View SearchResultsController here
How do I remove this?
Code for my SearchResultsController:
import UIKit
import CoreData
class SearchResultsController: UITableViewController, UISearchResultsUpdating {
var data:[String] = []
var filteredData:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredData.count
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
filteredData.removeAll(keepCapacity: true)
let searchString = searchController.searchBar.text
for info in data {
if (info.uppercaseString.rangeOfString(searchString.uppercaseString) != nil) {
filteredData.append(info)
}
}
tableView.reloadData()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = filteredData[indexPath.row]
return cell
}
}
in this app, when you select the second option 'green' it will print "green", but when you search for green and it appears at index 0, and you click on it, it will print "red". how do i get it to print "green" no mater what index and row green is on the table view?
thanks...
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchControllerDelegate, UISearchResultsUpdating, UISearchBarDelegate {
#IBOutlet weak var tableView: UITableView!
let sampleData:[String] = ["red", "green", "blue", "brown", "black", "white", "purple", "silver"]
var dataToDisplay:[String]!
var searchController:UISearchController!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.dataToDisplay = self.sampleData
self.tableView.delegate = self
self.tableView.dataSource = self
self.searchController = UISearchController(searchResultsController: nil)
self.searchController.delegate = self
self.searchController.searchBar.delegate = self
self.searchController.searchResultsUpdater = self
self.searchController.searchBar.sizeToFit()
self.tableView.tableHeaderView = self.searchController.searchBar
self.searchController.dimsBackgroundDuringPresentation = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataToDisplay.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Basic") as UITableViewCell
cell.textLabel?.text = self.dataToDisplay[indexPath.row]
return cell
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchString:String = searchController.searchBar.text
self.dataToDisplay = self.sampleData.filter ({ (dataString:String) -> Bool in
let match = dataString.rangeOfString(searchString)
if match != nil {
return true
}
else {
return false
}
})
self.tableView.reloadData()
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
self.tableView.hidden = false
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
self.tableView.hidden = false
}
func didDismissSearchController(searchController: UISearchController) {
self.tableView.hidden = false
}
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
if indexPath.row == 1 {
println("green")
}
if indexPath.row == 0 {
println("red")
}
}
I Figued out the answer...
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
var rownumber = indexPath.row
if dataToDisplay[rownumber] == sampleData[0] {
println("red")
}
}