I am implementing search controller programatically on navigation bar it is working fine and showing result, if I can select the tableview cell(did select method) segue is working fine . when I select the searched result it is not segue to next view controller. It is showing same view controller and tableview is reloading with data. I have show once click search result segue to next view controller
image
enter image description here
var modeldata = [ModelData]()
var FilerData = [ModelData]()
override func viewDidLoad() {
super.viewDidLoad()
self.searchcontroller = UISearchController(searchResultsController: nil)
self.searchcontroller.delegate = self
self.searchcontroller.searchBar.delegate = self
self.searchcontroller.hidesNavigationBarDuringPresentation = false
self.searchcontroller.dimsBackgroundDuringPresentation = true
self.navigationItem.titleView = searchcontroller.searchBar
self.definesPresentationContext = true
self.searchcontroller.searchResultsUpdater = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return modeldata.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
let row = indexPath.row
let values = modeldata[row] as ModelData
cell.NameLabel.text = values.name
return cell
}
func updateSearchResults(for searchController: UISearchController) {
let searchToSearch = searchController.searchBar.text
if(searchToSearch == "")
{
modeldata = self.FilerData
}
else{
modeldata.removeAll()
let itemsarray = self.FilerData
var ListArray = [String]()
for ListItems in itemsarray {
ListArray.append(ListItems.name!)
if(ListItems.name?.range(of: searchToSearch!, options: .caseInsensitive) != nil)
{
self.modeldata.append(ListItems)
}
}
}
self.TableView.reloadData()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "next", sender:indexPath.row )
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let selectrow = sender as? Int
let name = modeldata[selectrow!].name
let nextview = segue.destination as? WekiViewController
nextview?.namestring = name!
}
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.
My search is working correctly except the display is not working as expected. When I am performing a search, the last search result is slightly cut off and the portion of the display is all gray. I would expect it to remain the same background color as the rows.. Any help would be appreciated.
EDIT:
import UIKit
import Foundation
// For search
extension MasterViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchText: searchController.searchBar.text!)
}
}
class MasterViewController: UITableViewController {
let searchController = UISearchController(searchResultsController: nil)
var filteredFighters = [Fighter]()
var detailViewController: DetailViewController? = nil
var objects = [Any]()
// Creates array of fighters
var fighterArray = [Fighter]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
// Access all the data from JSON
let JR = JSONReceiver()
fighterArray = JR.populateFighterJSONArray()
// Search related
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
navigationItem.title = "UFC Champions"
self.navigationController?.navigationBar.barTintColor = UIColor.black
self.navigationController?.navigationBar.tintColor = UIColor.white
self.navigationController?.navigationBar.titleTextAttributes = [ NSForegroundColorAttributeName : UIColor.white, NSFontAttributeName: UIFont(name: "Arial", size: 26)!]
}
// FOr search
func filterContentForSearchText(searchText: String, scope: String = "All") {
filteredFighters = fighterArray.filter { fighter in
return fighter.name.lowercased().contains(searchText.lowercased())
}
tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/* DONT BELIEVE THIS IS NEEDED - DO NOT SEE IN PROFESSORS CODE
func insertNewObject(_ sender: Any) {
objects.insert(NSDate(), at: 0)
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.insertRows(at: [indexPath], with: .automatic)
} */
// MARK: - Segues
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Determines which row was selected (e.g. which fighters, say element 1 points to fighter1)
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
// let stud = StudentsArray[indexPath.row]
let fighter: Fighter
if searchController.isActive && searchController.searchBar.text != "" {
fighter = filteredFighters[indexPath.row]
} else {
fighter = fighterArray[indexPath.row]
}
let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
// Makes sure selected student points to the correct controller
controller.detailItem = fighter
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive && searchController.searchBar.text != "" {
return filteredFighters.count
}
return fighterArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let fighter: Fighter
if searchController.isActive && searchController.searchBar.text != "" {
fighter = filteredFighters[indexPath.row]
} else {
fighter = fighterArray[indexPath.row]
}
cell.textLabel!.text = fighter.name
cell.detailTextLabel?.text = fighter.record
cell.imageView?.image = UIImage(named: fighter.fighterImage)
self.tableView .sizeToFit()
// cell.detailTextLabel?.text = "fighterTest"
return cell
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return false
}
}
In VC1, I am trying to extract a string from an array, and send it to VC2. I do this in my prepareForSegue method. However, when I run it, there is a lag:
I tap row1(apples) in VC1 it goes to VC2 and shows apples in VC2
Tap back to VC 1
Tap row2(bananas), string passes as apples to
VC2
Tap back to VC1
I tap row3(oranges) in VC1 it goes to VC2
and shows bananas in VC2
etc etc.
Below is the code I am using. If anyone could help show me where I am going wrong, it would be much appreciated. Thank you..
class HomeSearchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating, UISearchBarDelegate {
var filteredArray = [String]()
var shouldShowSearchResults = false
var searchController: UISearchController!
var databaseRef = FIRDatabase.database().reference()
var loggedInUser = AnyObject?()
var loggedInUserData = AnyObject?()
var productSearchArray = [AnyObject?]()
var productBrandArray = [String]()
var itemNameArray = [String]()
var picUrlArray = [String]()
var skuArray = [String]()
var nextScreenRow = Int()
var nextSceenRowNonSearch = Int()
var toPass = String()
var toPassSearch = String()
var initialSearchList = ["Apple", "Samsung", "Windows", "Google"]
#IBOutlet weak var tblSearchResults: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
loadListOfCountries()
configureSearchController()
tblSearchResults.delegate = self
tblSearchResults.dataSource = self
}
// MARK: Table Cells Stuff
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if shouldShowSearchResults {
return filteredArray.count
}
else {
return initialSearchList.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("homeSearchCell", forIndexPath: indexPath) as! HomeSearchTableViewCell
//note to self: need to pass on more than one variable for search
if shouldShowSearchResults {
cell.configure(filteredArray[indexPath.row], itemNameLabel: "text'", skuLabel: "TEXT")
//cell.textLabel?.text = filteredArray[indexPath.row]
}
else if shouldShowSearchResults == false{
cell.configureNISearch(initialSearchList[indexPath.row])
}
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 60.0
}
//to find out row and pass variable.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
//println("You selected cell #\(indexPath.row)!")spDetailSegue
if shouldShowSearchResults {
nextScreenRow = indexPath.row
// get to the next screen
self.performSegueWithIdentifier("spDetailSegue", sender: self)
}
else if shouldShowSearchResults == false{
nextSceenRowNonSearch = indexPath.row
// get to the next screen
self.performSegueWithIdentifier("searchSegue", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "spDetailSegue") {
//Checking identifier is crucial as there might be multiple
// segues attached to same view
let detailVC = segue.destinationViewController as? pDetailViewController;
detailVC!.toPassSku = skuArray[nextScreenRow]
// print("vSku", )
}
if (segue.identifier == "searchSegue"){
//print("selected indexpath = ", selectedIndex)
let detailVC = segue.destinationViewController as? SearchDetailViewController;
detailVC!.toPassSearch = initialSearchList[nextSceenRowNonSearch]
}
}
//Search Bar stuff
func configureSearchController() {
// Initialize and perform a minimum configuration to the search controller.
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search here..."
searchController.searchBar.delegate = self
searchController.searchBar.sizeToFit()
//searchController.searchBar.scopeButtonTitles = ["Products", "Users"]
searchController.searchBar.barTintColor = UIColor.whiteColor()
searchController.searchBar.tintColor = UIColor.redColor()
// Place the search bar view to the tableview headerview.
tblSearchResults.tableHeaderView = searchController.searchBar
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
shouldShowSearchResults = true
tblSearchResults.reloadData()
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
shouldShowSearchResults = false
tblSearchResults.reloadData()
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
if !shouldShowSearchResults {
shouldShowSearchResults = true
tblSearchResults.reloadData()
}
searchController.searchBar.resignFirstResponder()
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchString = searchController.searchBar.text
// Filter the data array and get only those countries that match the search text.
filteredArray = itemNameArray.filter({ (item_name) -> Bool in
let countryText: NSString = item_name
return (countryText.rangeOfString(searchString!, options: NSStringCompareOptions.CaseInsensitiveSearch).location) != NSNotFound
})
// Reload the tableview.
tblSearchResults.reloadData()
}
}
once try by removing below line
tableView.deselectRowAtIndexPath(indexPath, animated: true)
from your didSelectRowAtIndexPath.
as #Lu_ suggested,
are you sure that didSelectRowAtIndexPath is called before prepareForSegue? you did not put your segue action from cell to controller?
This solved the issue. Thanks!
i have problem with segueing to view controller. I have table view with xib table view cell. Here is my code.
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
setupTableView()
setupDataSource()
}
private func setupTableView() {
tableView.backgroundColor = UIColor.clearColor()
tableView.allowsSelection = false
tableView.separatorColor = UIColor.clearColor()
tableView.registerNib(UINib(nibName: "ExampleTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! ExampleTableViewCell
let list = pariwisata[indexPath.row]
cell.nameLabel.text = list.name
cell.typeLabel.text = list.type
let image = objects[indexPath.row]
cell.apply(image)
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Row \(indexPath.row) selected")
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return tableView.bounds.width / 1.4
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
updateLocation(true)
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
updateLocation(false)
updateLocation(true)
}
func updateLocation(running: Bool) {
let mapView = self.view as! GMSMapView
let status = CLLocationManager.authorizationStatus()
if running {
if (CLAuthorizationStatus.AuthorizedWhenInUse == status) {
locationManager.startUpdatingLocation()
mapView.myLocationEnabled = true
mapView.settings.myLocationButton = true
}
} else {
locationManager.stopUpdatingLocation()
mapView.settings.myLocationButton = false
mapView.myLocationEnabled = false
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "showTop10Detail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let destinationController = segue.destinationViewController as! DetailViewController
destinationController.detpariwisata = pariwisata[indexPath.row]
}
}
I have no errors when build the project, but I cant tap on my table view. I mean, I can tap on my table view, but it print nothing. What did I miss? pls give me clue. Thanks!
1) You have to delete:
tableView.allowsSelection = false
2) Use this line to pass from one cell to another page (DetailPage for example):
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("toDetailPage", sender: indexPath)
}
3) Use this method to pass data to a DetailPage:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let indexPath = self.tableView.indexPathForSelectedRow
let person = personList[indexPath!.row]
if segue.identifier == "toDetailPage"{
let DetailBookViewController = (segue.destinationViewController as! DetailPage)
DetailBookViewController.user_name = user_name
DetailBookViewController.user_age = user_age
DetailBookViewController.user_urlPicture = user_urlPicture
}
4) Remember:
In your storyboard you have to link your tableViewController with your DetailPage
You have to declare a class for Person and declare:
var PersonList = [Person]()
You have to declare your var in tableView class and in DetailPage class
Remove this line of code:
tableView.allowsSelection = false
It is not allowing the selection of cell.
I'm getting errors whenever I try to reference the viewTable in the viewDidLoad AFTER I click on a cell to transition with the segue. Thanks a lot!!
Basically I can't use the segue unless I comment out the tableview references in view did load... but I need those in order to use the search bar and im sure it will cause problems on the way back...
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView! {
didSet {
print("tableView is set")
}
}
let searchController = UISearchController(searchResultsController: nil)
let textCellIdentifier = "TextCell"
var buildings: [(String,String)] = []
var filteredBuildings = [(String,String)]()
var goToIndex: Int?
override func viewDidLoad() {
super.viewDidLoad()
print(tableView)
var buildingTuples = loadBuildings()
for tuple in buildingTuples {
self.buildings.append(tuple)
}
self.goToIndex = -1
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView!.tableHeaderView = searchController.searchBar
}
func filterContentForSearchText(searchText: String, scope: String = "All") {
filteredBuildings = buildings.filter { building in
return building.0.lowercaseString.containsString(searchText.lowercaseString)
}
self.tableView.reloadData()
}
// MARK: UITextFieldDelegate Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return self.buildings.count
if searchController.active && searchController.searchBar.text != "" {
return filteredBuildings.count
}
return buildings.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
/*
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath)
let row = indexPath.row
cell.textLabel?.text = buildings[row].0
return cell
*/
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath)
let tuple: (String, String)
if searchController.active && searchController.searchBar.text != "" {
tuple = filteredBuildings[indexPath.row]
} else {
tuple = buildings[indexPath.row]
}
cell.textLabel?.text = tuple.0
return cell
}
// MARK: UITableViewDelegate Methods
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//tableView.deselectRowAtIndexPath(indexPath, animated: true)
let row = indexPath.row
self.goToIndex = indexPath.row
self.performSegueWithIdentifier("MainToLocation", sender: self)
//print(buildings[row].0)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "MainToLocation" {
let locationViewController = (segue.destinationViewController as! LocationViewController)
locationViewController.building = self.buildings[self.goToIndex!]
}
}
extension ViewController: UISearchResultsUpdating {
func updateSearchResultsForSearchController(searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!)
}
}
You can try this..
let destinationVC = self.storyboard!.instantiateViewControllerWithIdentifier("viewController") as! NextViewController
var alreadyPushed = false
if let vc = self.navigationController?.viewControllers {
for viewController in vc {
if let viewController = viewController as? NextViewController {
self.navigationController?.popToViewController(viewController, animated: true)
print("Push your controller")
alreadyPushed = true
break
}
}
}
if alreadyPushed == false {
self.navigationController?.pushViewController(destinationVC, animated: true)
}