I have a tableview implemented. The list shows fine, but I want to detect when the row selection has been changed. I am trying to do a certain action when the row selection is changed, for example, print("row selection has changed ")
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "exploreCell", for: indexPath)
cell.textLabel?.text = tableArray[indexPath.row]
return cell
}
I hope the question is clear.
You can observer selection state from this 2 delegate methods. So when you select any cell it will call didSelectRowAt delegate method and if you tap on selected cell again it will call didDeselectRowAt
Make sure to set tableView selection property to multiple selection incase if you want user to select multiple cell
tableView.allowsMultipleSelection = true
Swift Delegate methods.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Your code here
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
//Your code here
}
Related
I am doing expand/collapse when tapped on tableview cell, but I have to close all other cells except the tapped one. Tried this solution Expand only the cell that has been tapped this solution is not working for me.
below code which I have written for expand/collapse
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return datasource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView .dequeueReusableCell(withIdentifier: String(describing: ExpandingTableViewCell.self), for: indexPath) as! ExpandingTableViewCell
cell.set(content: datasource[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let content = datasource[indexPath.row]
content.expanded = !content.expanded
tableView.reloadRows(at: [indexPath], with: .automatic)
}
You need to collapse all cells and change the current clicked one state , then reload all the table
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let current = datasource[indexPath.row].expanded
datasource.forEach { $0.expanded = false }
let content = datasource[indexPath.row]
content.expanded = !current
tableView.reloadData()
}
Currently, I am trying to move a tableview cell from one table view to another. I can't seem to get the proper mechanics down and need help with this task.
Right now I have an array that is not filled with any goals for my progress table view cells.
var goals: [String] = []
Here is the setup for the rest of this progress table view.
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return goals[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TodayGoalViewCell_1", for: indexPath) as? GoalTableViewCell
cell?.goalLabel.text = goals[indexPath.section][indexPath.row]
cell?.cellDelegate = self
cell?.index = indexPath
return cell!
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
return goals.count
}
In a separate file I have another table view that is already filled with goals. Here is the code:
var goals = ["goal 1", "goal 2", "goal 3"]
extension GoalsViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Goals.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "GoalConversationsCell_1", for: indexPath)
cell.textLabel?.text = Goals[indexPath.row]
cell.textLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
cell.textLabel?.numberOfLines = 3
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 {
Goals.remove(at: indexPath.row)
Goals.count != 0 {
showGoalSelected()
} else {
Goals.append(contentsOf: theEmptyModel)
}
tableView.reloadData()
}
}
}
I would like to make it so that when a user selects a goal from the table view which already had goals, that these goals are moved to the progress table view. How would I do this?
If there is a button inside your cell and you want to get news when this button is clicked, you need to look at the protocol-delegate pattern.
But you can also try to remove the button inside the cell and use a text label. To use the didSelectRowAt method to catch clicking on cell, tableView in delegete.
I do not know what kind of design and structure you have, I just offer you perspective.
I am working on a todo list app and whenever I run it on the simulator and try to print the items in my array, the other cells item get printed.
Here's my code:
import UIKit
class TodoListViewController: UITableViewController {
let itemArray = ["math","english"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// DATASOURCE METHODS
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoItemCell", for: indexPath)
cell.textLabel?.text = itemArray[indexPath.row]
return cell
}
// DELEGATE METHODS
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
print(itemArray[indexPath.row])
}
}
You need didSelectRowAt not didDeselectRowAt , the latter is triggered when you select a row so you get the print from the previous selected row
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(itemArray[indexPath.row])
}
I just create the Bus ticket booking app. Now i want to save the search history (City Name and Date) and Display in my tableView. So this is what i coding in my SearchButtonAction.
#IBAction func btnSearchAction(_ sender: Any) {
if txtTo.text != nil && txtFrom.text != nil {
arrTo.append(txtTo.text!)
arrFrom.append(txtTo.text!)
UserDefault.set(arrTo, forKey: "arrTo")
UserDefault.set(arrFrom,forKey: "arrFrom")...
}
}
Now on my historyViewController I just coding like below
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrFrom.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RecentCell") as! RecentCell
cell.selectionStyle = .none
cell.lblFrom.text = arrFrom[indexPath.row]
cell.lblTo.text = arrTo[indexPath.row]
tblSearch.reloadData()
return cell
}
So it's Call only numberOfRowsInSection Method again and again Even arr count is more than one. What is the correct way to save two textField text in UserDefaults.
Remove reloading datas of tblSearch from cellForRowAt TableView data source method
When you reload tableview inside cellForRowAt method, tableview will go into looping. So you tableview won't display. So please remove tblSearch.reloadData() this line from cellForRow methhod.
please check screenshot, so you will get the better idea about looping.
http://prntscr.com/lte2mo
I have an alert in which I have used table view to show some data.
User can select any item from the table view data.
Now when I'm trying to select any item in didSelectRow method it isn't selecting an item. I have used breakpoints also but it isn't catching the breakpoints also.
I have given its delegates and datasources everything is fine but i'm confused why it isn't working?
My code is this:
extension YourOrdersViewController : UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return PreOrderService.instance.PreOrderModelInstance.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Hello")
print(PreOrderService.instance.PreOrderModelInstance[indexPath.row].perorder_time)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if tableView == orderTableView{
print("Dishes")
}
else{
orderTableView.cellForRow(at: indexPath)?.accessoryType = .none
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = orderTableView.dequeueReusableCell(withIdentifier: "orderCell", for: indexPath) as!
PreOrderTableViewCell
cell.titleLbl.text = PreOrderService.instance.PreOrderModelInstance[indexPath.row].perorder_time
print(cell.titleLbl.text!)
cell.selectionStyle = .none
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.accessoryType = cell.isSelected ? .checkmark : .none
return cell
}
}
View Controller looks like this,
enter image description here
Check or you have set this value:
If No Selection is set instead of Single Selection, the func tableView (_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) method will not be executed.
Does it have any gesture recognizer on your UIViewControlller. If it does and the gesture recognizer is above your table views on responder chain, it will take any single touch and leave nothing for your table views.
Whole problem in your code I think is:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
self.tableView.cellForRow(at: indexPath)?.accessoryType = .none
}
In Main.storyboard select your table view and in Attribute inspector change selection to single selection
Make sure that the delegate and datasource are set.
If you're creating the views via storyboard, make sure that you set the iboutlets for delegate/datasource.
Both of these lines mean the same thing: so remove the second one.
cell.selectionStyle = .none
cell.selectionStyle = UITableViewCellSelectionStyle.none