Show/hide table view cell using UISwitch - swift

I want to use UISwitch to show/hide a tableViewCell in a dynamic table view.
UISwitch is defined in a class of `UITableViewCell.
#IBOutlet weak var switchState: UISwitch!
And in the another file I want say if this switch is ON, the number of rows will be 5 otherwise it should be 4
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let test = PopupViewCell()
if test.switchState?.isOn == true {
detailsTableView.reloadData()
return 5
} else {
return 4
}
}
But it's not working, and it always read `return 4.
I also test it:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let test = PopupViewCell()
if test.switchState.isOn {
detailsTableView.reloadData()
return 5
} else {
return 4
}
}
But I will get this error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
I am not sure that I have to use some action function before this process or not, I will be appreciated if someone can help me on that.

The most beginner friendly way to do it is with a delegate. When the Switch cell detects a .valueChanged event it should forward this to the delegate. The delegate in turn updates its model of whether or not to show the switch and then reloads the tableView.
Here is a Playground example:
import UIKit
import PlaygroundSupport
protocol SwitchDelegate: class {
func toggle(isOn: Bool)
}
class SwitchCell: UITableViewCell {
private lazy var switchControl: UISwitch = {
let switchControl = UISwitch()
contentView.addSubview(switchControl)
switchControl.translatesAutoresizingMaskIntoConstraints = false
switchControl.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12).isActive = true
switchControl.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
switchControl.addTarget(self, action: #selector(toggleSwitch(_:)), for: .valueChanged)
return switchControl
}()
private weak var delegate: SwitchDelegate?
override func awakeFromNib() {
super.awakeFromNib()
}
func configure(isOn: Bool, delegate: SwitchDelegate) {
switchControl.isOn = isOn
self.delegate = delegate
}
#objc private func toggleSwitch(_ sender: UISwitch) {
delegate?.toggle(isOn: sender.isOn)
}
}
class ViewController: UITableViewController {
private let data = (0..<5).map { $0 + 1 }
private var isOn = true
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: String(describing: UITableViewCell.self))
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count + (isOn ? 1 : 0)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if isOn && indexPath.row == 0 {
let switchCell = SwitchCell(style: .default, reuseIdentifier: String(describing: SwitchCell.self))
switchCell.configure(isOn: isOn, delegate: self)
return switchCell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UITableViewCell.self), for: indexPath)
let dataIndex = indexPath.row - (isOn ? 1 : 0)
cell.textLabel?.text = String(describing: data[dataIndex])
return cell
}
}
}
extension ViewController: SwitchDelegate {
func toggle(isOn: Bool) {
self.isOn = isOn
tableView.reloadData()
}
}
PlaygroundPage.current.liveView = ViewController()

Related

How to delete a cell in the tableview from another View controller?

I am trying to delete a cell in the tableview from another view controller. I have modeled my code similar to the question posted below but I still can't seem to successfully delete the selected row/cell in the CalorieVC when the delete button is pressed in the DeleteVC
Deleting a row of a tableview from another viewcontroller
SideNote: there is button in the cells to popup the DeleteVC, I am also getting an error upon pressing the the deleteBtn in the CalorieVC: DeleteRowInTableviewDelegate on let picked saying Thread 1: Fatal error: Index out of range
import UIKit
class CalorieViewController: UIViewController {
var selectedFood: FoodList! // allows data to be passed into the CalorieVC
var deleteItems: CalorieItem? // passes data to DeleteVC
// allows data to be sepearted into sections
var calorieItems: [CalorieItem] = []
var groupedCalorieItems: [String: [CalorieItem]] = [:]
var dateSectionTitle: [String] = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.dataSource = self
tableView.delegate = self
// Allows data in cells to seperate by section
groupedCalorieItems = Dictionary(grouping: calorieItems, by: {$0.foodList.date})
dateSectionTitle = groupedCalorieItems.map{$0.key}.sorted()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "DeleteSegue" {
let vc: DeleteViewController = segue.destination as! DeleteViewController
vc.deleteItems = self.deleteItems
// vc.delegate = self
}
}
}
extension CalorieViewController: UITableViewDelegate, UITableViewDataSource{
func numberOfSections(in tableView: UITableView) -> Int {
return dateSectionTitle.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let date = dateSectionTitle[section]
return groupedCalorieItems[date]!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let calorieCell = tableView.dequeueReusableCell(withIdentifier: "CalorieCell") as! CalorieCell
let date = dateSectionTitle[indexPath.section]
let caloriesToDisplay = groupedCalorieItems[date]![indexPath.row]
calorieCell.configure(withCalorieItems: caloriesToDisplay.foodList)
return calorieCell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let calorieHeader = tableView.dequeueReusableCell(withIdentifier: "CalorieHeader") as! CalorieHeader
let headerTitle = dateSectionTitle[section]
calorieHeader.dateLbl.text = "Date: \(headerTitle)"
return calorieHeader
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 45
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let calorieFooter = tableView.dequeueReusableCell(withIdentifier: "CalorieFooter") as! CalorieFooter
//Cell Total Code
let date = dateSectionTitle[section]
let subtotal = groupedCalorieItems[dispensary]?.map { $0.getCalorieTotal() }.reduce(0, +) ?? 0
calorieFooter.calorieTotal.text = String(subtotal!)
return calorieFooter
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 150
}
}
extension CalorieViewController: DeleteRowInTableviewDelegate {
func deleteRow(inTableview rowToDelete: Int) {
let picked = dateSectionTitle[rowToDelete]
let selectedCell = groupedCalorieItems[dod]
delete(selectedCell)
// calorieItems.remove(at: rowToDelete) // tried using this and I get an error code upon segueing back to the CalorieVC
tableView.reloadData()
}
}
import UIKit
protocol DeleteRowInTableviewDelegate: NSObjectProtocol {
func deleteRow(inTableview rowToDelete: Int)
}
class DeleteViewController: UIViewController {
var modifyItems: CartItem!
var delegate: DeleteRowInTableviewDelegate?
#IBOutlet weak var deleteLbl: UILabel!
#IBOutlet weak var deleteBtn: UIButton!
#IBOutlet weak var cancelBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if isMovingFromParent {
delegate!.deleteRow(inTableview: 1)
}
deleteLbl.text = "Are you sure you want to delete this Food Item from your calorie List?"
}
#IBAction func decline(_ sender: Any) {
dismiss(animated: true)
delegate!.deleteRow(inTableview: 1)
print("Delete Item")
}
#IBAction func cancel(_ sender: Any) {
dismiss(animated: true)
print("Cancel Delete")
}
}
Remove the value from the dataSource
Remove the table cell
extension CalorieViewController: DeleteRowInTableviewDelegate {
func deleteRow(inTableview rowToDelete: Int) {
if caloriesItems.count > rowToDelete {
calorieItems.remove(at: rowToDelete)
tableView.deleteRows(at: [IndexPath(row: rowToDelete, section: 0)], with: .automatic)
} else {
print("index not present")
}
}
}
Do not call reloadData just to delete one row. This is a bad practice.
Use deleteRows instead.

How to hide a tableView after selecting a row

I have a textField, which when touch displays a tableView with some rows.
I'm trying to do this: when a user selects one of the rows, the value of row is placed in the textField and the tableView is closed.
The first part works well for me. The user touch on one row and the textField shows the value of that row. But if I want to close the tableview, I have to press twice on the row.
This is my code:
class Redactar_mensaje: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
var values = ["123 Main Street", "789 King Street", "456 Queen Street", "99 Apple Street", "red", "orange", "yellow", "green", "blue", "purple", "owaldo", "ostras", "Apple", "Pineapple", "Orange", "Adidas"]
#IBOutlet weak var campo_para: UITextField!
#IBOutlet weak var tableView: UITableView!
var originalCountriesList:[String] = Array()
override func viewDidLoad() {
super.viewDidLoad()
tableView.isHidden = true
for country in values {
originalCountriesList.append(country)
}
campo_para.delegate = self
tableView.delegate = self
tableView.dataSource = self
campo_para.addTarget(self, action: #selector(textFieldActive), for: UIControlEvents.touchDown)
campo_para.addTarget(self, action: #selector(searchRecords(_ :)), for: .editingChanged)
}
#objc func searchRecords(_ textField: UITextField) {
self.values.removeAll()
if textField.text?.count != 0 {
for country in originalCountriesList {
if let countryToSearch = textField.text{
let range = country.lowercased().range(of: countryToSearch, options: .caseInsensitive, range: nil, locale: nil)
if range != nil {
self.values.append(country)
}
}
}
} else {
for country in originalCountriesList {
values.append(country)
}
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return values.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cellx")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cellx")
}
cell?.textLabel?.text = values[indexPath.row]
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
campo_para.text = values[indexPath.row]
tableView.isHidden = true //I need press twice for this. I want press only one
}
func textFieldActive() {
tableView.isHidden = false
}
}
Ideally, the user touches the textField, displays the tableView, chooses one of the values, and it close automatically the tableView. But this last one does not work well.
Any advice?
Details
xCode 8.3, Swift 3.1
Example to Detect Double tap and Single tap on TableViewCell
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.tableFooterView = UIView()
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
cell.label.text = "\(indexPath)"
cell.delegate = self
return cell
}
}
extension ViewController:TableViewCellDelegate {
func tableViewCell(singleTapActionDelegatedFrom cell: TableViewCell) {
let indexPath = tableView.indexPath(for: cell)
print("singleTap \(String(describing: indexPath)) ")
}
func tableViewCell(doubleTapActionDelegatedFrom cell: TableViewCell) {
let indexPath = tableView.indexPath(for: cell)
print("doubleTap \(String(describing: indexPath)) ")
//You can hide your textfield here
}
}
TableViewCell.swift
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
private var tapCounter = 0
var delegate: TableViewCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
addGestureRecognizer(tap)
}
func tapAction() {
if tapCounter == 0 {
DispatchQueue.global(qos: .background).async {
usleep(250000)
if self.tapCounter > 1 {
self.doubleTapAction()
} else {
self.singleTapAction()
}
self.tapCounter = 0
}
}
tapCounter += 1
}
func singleTapAction() {
delegate?.tableViewCell(singleTapActionDelegatedFrom: self)
}
func doubleTapAction() {
delegate?.tableViewCell(doubleTapActionDelegatedFrom: self)
}
}
TableViewCellDelegate.swift
import UIKit
protocol TableViewCellDelegate {
func tableViewCell(singleTapActionDelegatedFrom cell: TableViewCell)
func tableViewCell(doubleTapActionDelegatedFrom cell: TableViewCell)
}
Result
Here I put my solution, in case someone else would happen something similar.
Just change the order of the lines and add one more line. First it makes it invisible and then puts the result in the textField and, magically, it worked!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.isHidden = true
campo_para.text = NombreUsuario[indexPath.row]
campo_asunto.becomeFirstResponder()
}
Thanks!

Swift 4 Switch relate to label on tableView

I have problem to get label from cell when i turn my switch ON. I do fetch all labels from Firebase Database.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tagCell", for: indexPath) as! TagsTableViewCell
print(myCallList[indexPath.row])
let _tag = myCallList[indexPath.row]
cell.tagLabel?.text = _tag.type
return cell
}
UPDATED:
UITableViewCell contain nothing special
import UIKit
class TagsTableViewCell: UITableViewCell {
#IBOutlet weak var tagLabel: UILabel!
#IBOutlet weak var tagSwitch: UISwitch!
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
}
}
My model:
class Calls: NSObject {
var type: String?
init(type: String?) {
self.type = type
}
}
LoadCalls contain Firebase data fetch:
func LoadCalls() {
ref = Database.database().reference()
let userID = Auth.auth().currentUser?.uid
self.myCallList.removeAll()
ref.child("tags").observe(.childAdded, with: { (snapshot) in
if snapshot != nil{
var tagType = snapshot.key as? String
let myCalls = Calls(type: tagType)
self.myCallList.append(myCalls)
print(self.myCallList.count)
DispatchQueue.main.async {
self.tagsTableView.reloadData()
}
}
})
}
A delegate / protocol for communication between cell and table controller can work well here.
protocol switchCellDelegate : Class {
func cellSwitchChanged( value: String, sender: Any)
}
update table view cell with property and IBAction for switch change
class TagsTableViewCell: UITableViewCell {
weak var delegate : switchCellDelegate?
#IBAction func switchChanged(sender: UISwitch){
guard let delegate = delegate else { return }
if sender.isOn {
delegate.cellSwitchChanged( value: tagLabel.text, sender: self)
}
}
and then in cellForRowAtIndex, add this
cell.delegate = self
and controller
extension myController : switchCellDelegate {
func cellSwitchChanged( value: String, sender: Any){
//do what you want here
}
}
I guess it something like this - add tag to switcher and create action for it
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tagCell", for: indexPath) as! TagsTableViewCell
print(myCallList[indexPath.row])
let _tag = myCallList[indexPath.row]
cell.tagLabel?.text = _tag.type
cell.switcher.tag = indexPath.row
return cell
}
And after this
#IBAction func switcherChanged(_ sender: UISwitch) {
var getLabel = myCallList[(sender as AnyObject).tag]
print(getLabel.type)
}

How to recognize which cell was tapped once and which was tapped twice

there! I would like to get to know which cell is tapped once and which is tapped twice. I have two classes, one for TableViewController and the other one for TableViewCell. I would like to manipulate cells regarding the touch but I cannot get their indexPath.
TableViewController:
import UIKit
var elements: [[Int16]] = Array(repeating:Array(repeating:0, count:2), count:10)
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return elements.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
if(elements[indexPath.row][1] == 1) //if red
{
cell.Label.text = String(elements[indexPath.row][0] * 3)
cell.Circle.backgroundColor = UIColor.red
}
else //if blue
{
cell.Label.text = String(elements[indexPath.row][0])
cell.Circle.backgroundColor = UIColor.blue
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return UIScreen.main.bounds.height/10
}
override func viewWillAppear(_ animated: Bool)
{
for i in 0..<elements.count
{
elements[i][0] = Int16(Int(arc4random_uniform(10)))
elements[i][1] = Int16(Int(arc4random_uniform(2)))
}
Memory().save(entity: elements)
}
override func viewDidLoad()
{
super.viewDidLoad()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
}
TableViewCell:
import UIKit
class TableViewCell: UITableViewCell
{
override func awakeFromNib()
{
super.awakeFromNib()
Circle.layer.cornerRadius = Circle.frame.width / 2
let singleTap = UITapGestureRecognizer(target: self, action: #selector(tappedOnce))
singleTap.numberOfTapsRequired = 1
addGestureRecognizer(singleTap)
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(tappedTwice))
doubleTap.numberOfTapsRequired = 2
addGestureRecognizer(doubleTap)
singleTap.require(toFail: doubleTap)
singleTap.delaysTouchesBegan = true
doubleTap.delaysTouchesBegan = true
}
override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
#objc func tappedOnce(sender: AnyObject?)
{
print("1111111")
//Memory().reload(reload: x, I: x)
}
#objc func tappedTwice()
{
print("2222222")
}
#IBOutlet weak var Label: UILabel!
#IBOutlet weak var Circle: UIView!
}
Inside the cells I have a label storing a random number (label) from 0 to 10 next to which there is a circle - blue or red (they are also random at start). If the circle is red, then the number (label) shows the number multiplied by three. All this is there.
Now... I want to change the number by touching on the cell once and make it 0 by touching on it twice
TableViewController:
var elements: [[Int16]] = Array(repeating: Array(repeating:0, count:2), count:10)
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
//MARK: - UIViewController LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
for i in 0..<elements.count {
elements[i][0] = Int16(Int(arc4random_uniform(10)))
elements[i][1] = Int16(Int(arc4random_uniform(2)))
}
Memory().save(entity: elements)
}
//MARK: - UITableView Delegate & DataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return elements.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
if elements[indexPath.row][1] == 1 {
cell.Label.text = String(elements[indexPath.row][0] * 3)
cell.Circle.backgroundColor = UIColor.red
}
else {
cell.Label.text = String(elements[indexPath.row][0])
cell.Circle.backgroundColor = UIColor.blue
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UIScreen.main.bounds.height/10
}
}
TableViewCell:
class TableViewCell: UITableViewCell {
#IBOutlet weak var Label: UILabel!
#IBOutlet weak var Circle: UIView!
private var tapCounter = 0
override func awakeFromNib() {
super.awakeFromNib()
Circle.layer.cornerRadius = Circle.frame.width / 2
let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
addGestureRecognizer(tap)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#objc func tapAction() {
if tapCounter == 0 {
DispatchQueue.global(qos: .background).async {
usleep(250000)
if self.tapCounter > 1 {
self.tappedTwice()
}
else {
self.tappedOnce()
}
self.tapCounter = 0
}
}
tapCounter += 1
}
func tappedOnce() {
print("1111111")
}
func tappedTwice() {
print("2222222")
}
}
Take reference from here
Single and double taps on UITableViewCell in Swift 3

Swift UiTableView not reloading search results

I am having a weird issue where for some reason my UITableView is not being reloading after performing a search. The console prints out the correctly filtered data, but the table simply doesn't change. I have never encountered this issue, so I first attempted the solutions which naturally came to mind:
Tried tableView.reloadData() in the Main Queue
Quit Xcode, clean build, reinstall
Cleared out the derived data dir
I have found several similar issue in SO, but all of the solutions I've seen are things I've tried, mainly reloading tableview in main queue.
Hoping maybe I just simply have an issue in my code or something I'm missing.
I am running Xcode 8.3.3
import UIKit
class CategoriesViewController: UIViewController {
var isFiltering = false
var location = Location()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
var categoriesSearchResults = [Category]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.allowsSelection = true
tableView.keyboardDismissMode = .onDrag
let nib = UINib(nibName: "CategoryTableViewCell", bundle: nil)
self.tableView.register(nib, forCellReuseIdentifier:"CategoryTableViewCell");
searchBar.returnKeyType = UIReturnKeyType.done
searchBar.autocapitalizationType = .none
searchBar.delegate = self
}
extension CategoriesViewController : UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("HI")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering {
return self.categoriesSearchResults.count
}
return self.location.categories.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
if let cell = self.tableView.dequeueReusableCell(withIdentifier: "CategoryTableViewCell", for: indexPath) as? CategoryTableViewCell {
var category: Category
if isFiltering {
category = self.categoriesSearchResults[indexPath.row]
} else {
category = self.location.categories[indexPath.row]
}
cell.name.text = category.name
cell.status.textColor = UIColor.lightGray
cell.status.text = "Not Verified"
}
return cell
}
}
extension CategoriesViewController : UISearchBarDelegate {
func searchBarIsEmpty() -> Bool{
return self.searchBar.text?.isEmpty ?? true
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
self.isFiltering = true
self.categoriesSearchResults.removeAll()
tableView.reloadData()
self.view.endEditing(true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBarIsEmpty() {
self.view.endEditing(true)
self.isFiltering = false
} else {
self.isFiltering = true
self.categoriesSearchResults = self.location.categories.filter({ (category: Category) -> Bool in
return category.name.lowercased().contains(searchText.lowercased())
})
}
tableView.reloadData()
}
}
and my custom table view cell:
import UIKit
class CategoryTableViewCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var status: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func prepareForReuse() {
super.prepareForReuse()
self.name.text = ""
self.status.text = ""
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Thank you in advance.
EDIT: Might also be worth mentioning, when I am actively searching, the function tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) is not called??
The scope of if let nests in its scope. In your code you are always returning let cell = UITableViewCell(). Try returning it inside the if let :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
if let cell = self.tableView.dequeueReusableCell(withIdentifier: "CategoryTableViewCell", for: indexPath) as? CategoryTableViewCell {
var category: Category
if isFiltering {
category = self.categoriesSearchResults[indexPath.row]
} else {
category = self.location.categories[indexPath.row]
}
cell.name.text = category.name
cell.status.textColor = UIColor.lightGray
cell.status.text = "Not Verified"
/// RETURN CELL HERE
return cell
}
return cell
}