Swift - Having problems with SearchBar in a custom TableViewController - ios

I am new to code and I want to make an Search function in my Custom TableViewController. I get an error (Thread 1: signal SIGABRT) when I type (in the search bar) in a letter which correspond to a letter in an list of names (var namen*) I made. When I type in a letter which not correspond to a letter in my list of names I don't get the error. I checked my IBoutlets but they were not the problem. Does someone know how to fix the error?
Here's my initial viewcontroller code: (some names are Dutch)
import UIKit
class elementstableviewcontroller: UITableViewController,
UISearchResultsUpdating{
#IBOutlet var tableview: UITableView!
var namen = ["Waterstof","Helium","Litium","Beryllium","Boor","Koolstof","Stikstof","Zuurstof","Fluor","Neon"]
var afkortingen = ["H","He","Li","Be","B","C","N","O","F","Ne"]
var atoommassas = ["Massa: 1,008","Massa: 4,003","Massa: 6,941","Massa: 9,012","Massa: 10,81","Massa: 12,01","Massa: 14,01","Massa: 16,00","Massa: 19,00","Massa: 20,18"]
var atoomnummers = ["Nummer: 1","Nummer: 2","Nummer: 3","Nummer: 4","Nummer: 5","Nummer: 6","Nummer: 7","Nummer: 8","Nummer: 9","Nummer: 10"]
var ladingen = ["Lading: +1,-1","Lading: 0","Lading: +1","Lading: +2","Lading: +3","Lading: +2,+4,-4","Lading: +1,+2,+3,+4,+5,-1,-2,-3","Lading: -2","Lading: -1","Lading: 0"]
var electronenconfig = ["Config: 1","Config: 2","Config: 2,1","Config: 2,2","Config: 2,3","Config: 2,4","Config: 2,5","Config: 2,6","Config: 2,7","Config: 2,8"]
var searchcontroller : UISearchController!
var resultscontroller = UITableViewController()
var filterednamen = [String]()
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
definesPresentationContext = true
}
func updateSearchResults(for searchController: UISearchController) {
self.filterednamen = self.namen.filter { (naam:String) -> Bool in
if naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased()) {
return true
}else{
return false
}
}
self.resultscontroller.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.tableView{
return self.namen.count
}else {
return self.filterednamen.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.afkorting.text = afkortingen[indexPath.row]
cell.name.text = namen[indexPath.row]
cell.atoommassa.text = atoommassas[indexPath.row]
cell.elektronenconfiguratie.text = electronenconfig[indexPath.row]
cell.atoomnummer.text = atoomnummers[indexPath.row]
cell.lading.text = ladingen[indexPath.row]
if tableView == self.tableView{
//cell.textLabel?.text = self.namen[indexPath.row]
cell.name.text = self.namen[indexPath.row]
}else{
//cell.textLabel?.text = self.filterednamen[indexPath.row]
cell.name.text = self.filterednamen[indexPath.row]
}
return cell
}
}
And here's my CustomCell code:
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet var elektronenconfiguratie: UILabel!
#IBOutlet var atoomnummer: UILabel!
#IBOutlet var atoommassa: UILabel!
#IBOutlet var name: UILabel!
#IBOutlet var afkorting: UILabel!
#IBOutlet var lading: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
*namen = names and naam = name translated from Dutch to English

Try to implement filter functionality in shouldChangeTextIn SearchBar method as given below
func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
self.filterednamen = self.namen.filter { (naam:String) -> Bool in
return naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased())
}
self.resultscontroller.tableView.reloadData()
}

There are several problems with your code.
Firstly, you are creating an IBOutlet of a UITableView unnecessarily. Remove that from your code.
Secondly, you are using that table view for checking if you are searching or not. That is unneccesary, as you want to show search results in the same view controller, so the correct boolean check for that instead is:
!searchcontroller.isActive || searchcontroller.searchBar.text == ""
Lastly, the error occurs exactly because the last issue stated: you are setting the searchResultsController to a phantom table view, so it gets an assertion failure, as it can't find a cell identified "cell".
Here is the fixed code:
import UIKit
class FirstViewController: UITableViewController,
UISearchResultsUpdating{
var namen = ["Waterstof","Helium","Litium","Beryllium","Boor","Koolstof","Stikstof","Zuurstof","Fluor","Neon"]
var afkortingen = ["H","He","Li","Be","B","C","N","O","F","Ne"]
var atoommassas = ["Massa: 1,008","Massa: 4,003","Massa: 6,941","Massa: 9,012","Massa: 10,81","Massa: 12,01","Massa: 14,01","Massa: 16,00","Massa: 19,00","Massa: 20,18"]
var atoomnummers = ["Nummer: 1","Nummer: 2","Nummer: 3","Nummer: 4","Nummer: 5","Nummer: 6","Nummer: 7","Nummer: 8","Nummer: 9","Nummer: 10"]
var ladingen = ["Lading: +1,-1","Lading: 0","Lading: +1","Lading: +2","Lading: +3","Lading: +2,+4,-4","Lading: +1,+2,+3,+4,+5,-1,-2,-3","Lading: -2","Lading: -1","Lading: 0"]
var electronenconfig = ["Config: 1","Config: 2","Config: 2,1","Config: 2,2","Config: 2,3","Config: 2,4","Config: 2,5","Config: 2,6","Config: 2,7","Config: 2,8"]
var searchcontroller : UISearchController!
var filterednamen = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.searchcontroller = UISearchController(searchResultsController: nil)
self.tableView.tableHeaderView = self.searchcontroller.searchBar
self.searchcontroller.searchResultsUpdater = self
self.searchcontroller.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
}
func updateSearchResults(for searchController: UISearchController) {
self.filterednamen = self.namen.filter { (naam:String) -> Bool in
if naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased()) {
return true
}else{
return false
}
}
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
return self.namen.count
}else {
return self.filterednamen.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.afkorting.text = afkortingen[indexPath.row]
cell.name.text = namen[indexPath.row]
cell.atoommassa.text = atoommassas[indexPath.row]
cell.elektronenconfiguratie.text = electronenconfig[indexPath.row]
cell.atoomnummer.text = atoomnummers[indexPath.row]
cell.lading.text = ladingen[indexPath.row]
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
//cell.textLabel?.text = self.namen[indexPath.row]
cell.name.text = self.namen[indexPath.row]
}else{
//cell.textLabel?.text = self.filterednamen[indexPath.row]
cell.name.text = self.filterednamen[indexPath.row]
}
return cell
}
}

Related

UISearchBar to filter custom UITableViewCells

I am trying to filter custom UITableViewCells, based on one of the UILabels present in the cell.
All of the data is parsed from remote JSON, which has the model locally named Item and currently I am displaying the following in each cell successfully:
var titleLabel = UILabel()
var descriptionLabel = UILabel()
Also defined in my ItemTableViewCell class is:
func set(product: Item) {
DispatchQueue.main.async { [weak self] in
self?.titleLabel.text = item.title
self?.descriptionLabel.text = item.listPrice
}
}
These are called within my main View Controller, to which I have added a searchBar successfully and is visible within the app:
import Foundation
import UIKit
class ItemsListViewController: UIViewController {
var items = [Items]()
var itemsSearch: [Items] = []
var tableView = UITableView()
var searchController = UISearchController()
struct Cells {
static let itemCell = "ItemCell"
}
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
configureSearchController()
}
func configureSearchController() {
searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
searchController.searchBar.placeholder = "Search items"
definesPresentationContext = true
var isSearchBarEmpty: Bool {
return searchController.searchBar.text?.isEmpty ?? true
}
}
func configureTableView() {
view.addSubview(tableView)
setTableViewDelegates()
tableView.rowHeight = 100
tableView.pin(to: view)
tableView.register(itemTableViewCell.self, forCellReuseIdentifier: Cells.itemCell)
}
func setTableViewDelegates() {
tableView.delegate = self
tableView.dataSource = self
}
}
extension itemsListViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Cells.itemCell) as! itemTableViewCell
let item = items[indexPath.row]
cell.set(item: item)
return cell
}
}
extension ItemsListViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
let searchBar = searchController.searchBar
}
}
How can I filter these cells so say for instance a user searches for "Food", the only items which return would be ones which have a cell titleLabel = "food"?
I've tried to implement a function similar to the below, however it fails to achieve what I am after:
func filterContentForSearchText(_ searchText: String, category: = nil) {
let cell = tableView.dequeueReusableCell(withIdentifier: Cells.productCell) as! ProductTableViewCell
productsSearch = products.filter { (cell: cell) -> Bool in
return products.name.lowercased().contains(searchText.lowercased())
}
tableView.reloadData()
}
Thanks in advance for any help here.
You can not filter TableViewCells. You have to filter your model data and instead of using UISearchResultsUpdating you should use UISearchBarDelegate
I have modified your code, check it.
class ItemsListViewController: UIViewController {
var items = [Items]()
var itemsSearch: [Items] = []
var filterActive = false
var tableView = UITableView()
var searchController = UISearchController()
struct Cells {
static let itemCell = "ItemCell"
}
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
configureSearchController()
}
func configureSearchController() {
searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
searchController.searchBar.placeholder = "Search items"
searchController.searchBar.delegate = self
definesPresentationContext = true
}
func configureTableView() {
view.addSubview(tableView)
setTableViewDelegates()
tableView.rowHeight = 100
tableView.pin(to: view)
tableView.register(itemTableViewCell.self, forCellReuseIdentifier: Cells.itemCell)
}
func setTableViewDelegates() {
tableView.delegate = self
tableView.dataSource = self
}
}
extension ItemsListViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filterActive ? itemsSearch.count : items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Cells.itemCell) as! itemTableViewCell
let item = filterActive ? itemsSearch[indexPath.row] : items[indexPath.row]
cell.set(item: item)
return cell
}
}
extension ItemsListViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filterItems(text: searchController.searchBar.text)
}
func filterItems(text: String?) {
guard let text = text else {
filterActive = false
self.tableView.reloadData()
return
}
self.itemsSearch = self.items.filter({ (item) -> Bool in
return item.title.lowercased().contains(text.lowercased())
})
filterActive = true
self.tableView.reloadData()
}
// Edited Version
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.text = nil
filterActive = false
self.tableView.reloadData()
}
}
You are doing it the wrong way.
You should not filter the cells, but instead filter the model (e.g. add and remove entries to the table view data source)
Then call reloadData - this will then access the filtered model (in cellForRowAt and create only the filtered amount of (visible) cells
To improve, use a diffable data source

Create SearchController for reusable use

Is it possible to create UISearchController for reusable use in many classes?
To use a minimum of code in new classes.
Now I have code in all classes, but I want to use minimum code in all classes to call searchController:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
#IBOutlet weak var tableView: UITableView!
var photoBook: [PhotoBooking] = []
var filteredBook: [PhotoBooking] = []
private var searchController = UISearchController(searchResultsController: nil)
private var searchBarIsEmpty: Bool {
guard let text = searchController.searchBar.text else { return false }
return text.isEmpty
}
private var isFiltering: Bool {
return searchController.isActive && !searchBarIsEmpty
}
override func viewDidLoad() {
super.viewDidLoad()
configureSearchController()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering {
return filteredBook.count
}
return photoBook.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
var pBook: PhotoBooking
if isFiltering {
pBook = filteredBook[indexPath.row]
} else {
pBook = photoBook[indexPath.row]
}
cell.textLabel?.text = pBook.invoiceID
cell.detailTextLabel?.text = pBook.contactInfo["surname"] as! String
return cell
}
private func configureSearchController() {
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.searchBar.barTintColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.delegate = self
tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
}
}
extension AllPhotoBookingsViewController: UISearchResultsUpdating {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
filterContentForSearchText(searchBar.text!)
tableView.reloadData()
}
func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!)
tableView.reloadData()
}
private func filterContentForSearchText(_ searchText: String) {
filteredBook = photoBook.filter({ (book: PhotoBooking) -> Bool in
let name = book.contactInfo["name"] as! String
let surname = book.contactInfo["surname"] as! String
let invoice = book.invoiceID
return invoice.localizedCaseInsensitiveContains(searchText) ||
name.localizedCaseInsensitiveContains(searchText) ||
surname.localizedCaseInsensitiveContains(searchText)
})
tableView.reloadData()
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
navigationController?.hidesBarsOnSwipe = false
}
}
Maybe need use protocol, but I don't understand how to use correctly protocol.
There are many ways of doing this, using protocols is a great approach, but you could also subclass UIViewController and make a BaseSearchableViewController where you would add all the functionality you need for your search, then, you just subclass from BaseSearchableViewController instead of UIViewController.

SWIFT 4 UISearchBar and UITableView

I started a table view with a list of universities and created a search bar to tag along with it. The search bar works but only if I type in the name of the school exactly how it is. Is there a way I can change the it to search any part of the name and get the same results? Here's the code that I have set up.
#IBOutlet weak var schoolSearch: UISearchBar!
#IBOutlet weak var tblView: UITableView!
let schoolnames = ["Long Beach City College LAC", "California State University, Bakersfield", ...]
var searchedSchool = [String]()
var searching = false
override func viewDidLoad() {
super.viewDidLoad()
schoolSearch.delegate = self
self.tblView.delegate = self
self.tblView.reloadData()
}
extension ChooseSchool: UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return searchedSchool.count
} else {
return schoolnames.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableViewCell
cell?.img.image = UIImage(named: schoolnames[indexPath.row])
cell?.lbl.text = schoolnames[indexPath.row]
_ = tableView.dequeueReusableCell(withIdentifier: "cell")
if searching {
cell?.textLabel?.text = searchedSchool[indexPath.row]
} else {
cell?.textLabel?.text = schoolnames[indexPath.row]
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "TestController") as? TestController
vc?.schoolnames = schoolnames[indexPath.row]
navigationController?.pushViewController(vc!, animated: true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchedSchool = schoolnames.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
searching = true
tblView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tblView.reloadData()
}
}
Replace
searchedSchool = schoolnames.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
with
searchedSchool = schoolnames.filter { $0.range(of: searchText, options: .caseInsensitive) != nil }
I think you have to make your searchBar implement the containsString method to achieve what you need. For reference look at this link

Swift - Segue to wrong index when UISearchBar is active

I am new to code, and I just can't find the solution to this problem. Most of the answers on the internet are deprecated or unanswered.
I want to search something into my searchbar, after that I want to press on one of the results. When I click on the result I want it to give me the corresponding information in another viewcontroller.
Here's my problem: When I click on a result, the information in the other viewcontroller doesn't correspond with the information that the result gave me. What he does gives me is the information that corresponds to the tableview. So, it segues with a wrong index. Does anyone knows what the solution is?
Here's my code (tableviewcontroller with searchbar):
var myIndex = 0
extension UIColor { //themakleur
static let candyGreen = UIColor(red: 71.0/255.0, green: 81.0/255.0, blue:
89.0/255.0, alpha: 1.0)}
var watjeberekend = ["Omtrek Cirkel","Oppervlakte Cirkel","Lengte
Boog","Oppervlakte Sector","Oppervlakte Bol"]
class scheikunde: UITableViewController, UISearchResultsUpdating {
var scheikundeformules = ["Omtrek Cirkel","Oppervlakte Cirkel","Lengte Boog","Oppervlakte Sector","Oppervlakte Bol"]
var searchcontroller : UISearchController!
var filterednamen = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.searchcontroller = UISearchController(searchResultsController: nil)
self.tableView.tableHeaderView = self.searchcontroller.searchBar
self.searchcontroller.searchResultsUpdater = self
self.searchcontroller.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
self.navigationItem.hidesBackButton = false;
self.navigationController?.isNavigationBarHidden = false
//navigationcontroller layout
navigationController?.navigationBar.barTintColor = UIColor(red: 71.0/255.0, green: 81.0/255.0, blue: 89.0/255.0, alpha: 1.0)
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
navigationController?.navigationBar.layer.borderColor = UIColor.candyGreen.cgColor
navigationController?.navigationBar.layer.borderWidth = 0
//searchcontroller layout
searchcontroller.searchBar.layer.borderWidth = 0
searchcontroller.searchBar.layer.borderColor = UIColor.candyGreen.cgColor
UISearchBar.appearance().barTintColor = .candyGreen
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = .candyGreen
searchcontroller.searchBar.backgroundImage = UIImage(named: "themakleur.jpg")
let cancelButtonAttributes: [String: AnyObject] = [NSForegroundColorAttributeName: UIColor.white]
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(cancelButtonAttributes, for: .normal)
}
func updateSearchResults(for searchController: UISearchController) {
self.filterednamen = self.scheikundeformules.filter { (naam : String) -> Bool in
if naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased()) {
return true
}else{
return false}}
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
return self.scheikundeformules.count
}else {
return self.filterednamen.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Custommath
cell.label.text = scheikundeformules[indexPath.row]
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
//cell.textLabel?.text = self.namen[indexPath.row]
cell.label.text = self.scheikundeformules[indexPath.row]
}else{
//cell.textLabel?.text = self.filterednamen[indexPath.row]
cell.label.text = self.filterednamen[indexPath.row]
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex = indexPath.row
performSegue(withIdentifier: "segue", sender: self)
}
}
Here is my code from the viewcontroller:
import UIKit
class scheikundeformule: UIViewController{
#IBOutlet var uitleg6: UILabel!
#IBOutlet var formuleomschrijving: UILabel!
#IBOutlet var uitleg5: UILabel!
#IBOutlet var uitleg4: UILabel!
#IBOutlet var uitleg3: UILabel!
#IBOutlet var uitleg2: UILabel!
#IBOutlet var uitleg1: UILabel!
#IBOutlet var titlelabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
titlelabel.text = scheikundeformules[myIndex]
uitleg1.text = uitlegformules2[myIndex]
uitleg2.text = uitlegformules3[myIndex]
uitleg3.text = uitlegformules4[myIndex]
uitleg4.text = uitlegformules5[myIndex]
uitleg5.text = uitlegformules6[myIndex]
uitleg6.text = uitlegformules7[myIndex]
self.navigationItem.hidesBackButton = false;
self.navigationController?.isNavigationBarHidden = false
formuleomschrijving.text = watjeberekend[myIndex]
//keyboard weg deel 1
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(startscreen.dismissKeyboard))
//Uncomment the line below if you want the tap not not interfere and cancel other interactions.
//tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
Where is your function prepare for segue ? if you want to pass the data to the next view controller you need to send it in the fun prepare for segue, and remember that the indexpath.row needs to be used with the array that is the current datasource of the tableview, the solution will be something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationVC = segue.destination as? YourViewController {
if !searchcontroller.isActive {
destinationVC.name = filterednamen[myIndex]
} else {
destinationVC.name = scheikundeformules[myIndex]
} }
}
Add identifier for scheikundeformule view controller in storyboard like below :
Step 1:
Step 2:
change your tableview didSelectRow like below :
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex = indexPath.row
let scheikundeformuleController = self.storyboard?.instantiateViewController(withIdentifier: "scheikundeformule") as! scheikundeformule
scheikundeformuleController.myIndex = indexPath.row
self.present(scheikundeformuleController, animated: true, completion: nil)
}
Step 3:
You have to add var myIndex = 0 to your scheikundeformule controller. Like below :
class scheikundeformule: UIViewController{
var myIndex = 0
........Your code
}

Swift Search Results segue to other View controller

When I search in my searchbar, I want to click on a result and then go to another view controller. I found a similar queston on this site (Swift Search Result Controller in search results segue to another view controller) but it didn't worked out for me.
With my current code there is a working segue, but it is the table view segue (instead of the results segue).
Does someone know how I do this and explain it in an easy way?
Here's my tableviewcontroller code:
class elementstableviewcontroller: UITableViewController,
UISearchResultsUpdating{
var namen = ["Waterstof","Helium","Litium"]
var searchcontroller: UISearchController!
var resultsController: UISearchController!
var filterednamen = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.searchcontroller = UISearchController(searchResultsController: nil)
self.tableView.tableHeaderView = self.searchcontroller.searchBar
self.searchcontroller.searchResultsUpdater = self
self.searchcontroller.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
self.navigationItem.hidesBackButton = false;
self.navigationController?.isNavigationBarHidden = false
}
func updateSearchResults(for searchController: UISearchController) {
self.filterednamen = self.namen.filter { (naam:String) -> Bool in
if naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased()) {
return true
}else{
return false
}
}
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
return self.namen.count
}else {
return self.filterednamen.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.name.text = namen[indexPath.row]
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
cell.name.text = self.namen[indexPath.row]
}else{
cell.name.text = self.filterednamen[indexPath.row]
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex2 = indexPath.row
performSegue(withIdentifier: "segue2", sender: self)
}
}
and here's my second view controller code:
import UIKit
import GoogleMobileAds
class Elementenuitgelegd: UIViewController, GADBannerViewDelegate{
#IBOutlet var banner: GADBannerView!
#IBOutlet var uitleg5: UILabel!
#IBOutlet var groep: UILabel!
#IBOutlet var periode: UILabel!
#IBOutlet var uitleg4: UILabel!
#IBOutlet var uitleg3: UILabel!
#IBOutlet var uitleg2: UILabel!
#IBOutlet var uitleg1: UILabel!
#IBOutlet var titlelabel: UILabel!
var distance: Double = 0;
var speed: Double = 0;
var time: Double = 0;
override func viewDidLoad() {
super.viewDidLoad()
titlelabel.text = namen[myIndex2]
uitleg1.text = afkortingen[myIndex2]
uitleg2.text = atoommassas[myIndex2]
uitleg3.text = atoomnummers[myIndex2]
uitleg4.text = electronenconfig[myIndex2]
periode.text = periodes[myIndex2]
groep.text = groepen[myIndex2]
self.navigationItem.hidesBackButton = true;
self.navigationController?.isNavigationBarHidden = true
//banner
let request = GADRequest()
request.testDevices = [kGADSimulatorID]
banner.adUnitID = "ca-app-pub-8478021432040036/4295805958"
banner.rootViewController = self
banner.delegate = self
banner.load(request)
//keyboard weg deel 1
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(startscreen.dismissKeyboard))
//Uncomment the line below if you want the tap not not interfere and cancel other interactions.
//tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//keyboardweg deel 2
func dismissKeyboard() {
view.endEditing(true)
}
}
Here's my customcell controller code:
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet var name: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
[First(tableview),second(searching for Neon and clicking on it), third(getting hydrogen("waterstof" in Dutch)1

Resources