TableView didSelect method and toggle [closed] - toggle

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have tableView I need to select 3 cells and and even I scroll it will be stay like. I can select 1, 2 or 3 cells but not 4 or more.When I select 4 cells nothing should happen. If there are 3 selected cells and I click one of them the cell which I selected should be deselected.

If you have a model, use the model. Modifying only the view is not persistent.
In the model add a property
var isSelected = false
in cellForRowAt set isSelected according to the model (assuming items is the data source array)
let item = items[indexPath.row]
cell.isSelected = item.isSelected
Implement willSelectRowAt to handle the 3-items restriction by filtering and counting the selected items. If the method returns nil the row cannot be selected.
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
return items[indexPath.row].isSelected || items.filter{$0.isSelected}.count < 3 ? indexPath : nil
}
In didSelect toggle isSelected and reload the row
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
items[indexPath.row].isSelected.toggle()
tableView.reloadRows(at: [indexPath], with: .automatic)
}
indexPathsForSelectedRows and allowsMultipleSelection is not needed respectively the latter must set to true permanently.

Related

TableView DidSelectRowAt will change background colors of other cells when I scroll

I have a TableView sometimes with enough cells allowing me to scroll through the table. At the same time I have set my didSelectRow to switch the background color of the cell. It seems that after selecting a few then scrolling down I find that more cells have been selected out of my control.
Here is my didSelectRowAt:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
packSizesTableView.cellForRow(at: indexPath)?.backgroundColor = UIColor.yellow
packList[indexPath.row].picked = true
pickedRows.append(indexPath)
Is there another way I should be selecting my table cells other than changing the color if the indexPath.row?
You can set cell color in cellForRowAt method as below:-
If packList[indexPath.row].picked {
yourCell.backgroundColor = UIColor.yellow
} else {
yourCell.backgroundColor = UIColor.red
}
Short answer: You are seeing the colors change on the wrong cells because cells get reused, and you need to set the color to the correct option when a cell is reused.
In the tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) method you can check your packList array to see if the cell being dequeued needs to be selected or not and set the color there. This will handle cases where a new cell is being created as well as cells that are being reused.
if packList[indexPath.row].picked {
cell.backgroundColor = UIColor.selectedColor
} else {
cell.backgroundColor = UIColor.defaultColor
}
You have several options for handling selecting/deselecting, so here is one option. In tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) you can simply do:
packList[indexPath.row].picked = !packList[indexPath.row].picked
tableView.reloadRows(at: [indexPath], with: UITableView.RowAnimation.whateverYouWant)
You could also do just update your packList array (which is needed for cellForRow), and override the logic in your cell's func setSelected(_ selected: Bool, animated: Bool) method.

How to get didselectrowat from a custom cell with textboxes?

I have a dynamic tableview with 3(cell1,cell2,cell3) custom cells, which gets reused anywhere from 0 times up to 9 times. (Maximum cells in the tableview will be 27 cells).
Each of those 3 custom cells have 3 text boxes each, and in addition the second cell has 2 buttons to select gender and 3rd custom cell has a drop down menu, which has values of whatever typed in the first textbox of cell1 cells.
Now the issue is that, textbox takes the touch input from user (as it should) and didselectrowat never gets called and therefore i am not getting indexPath.
But i need the indexPath, so that i can insert user details from each of those cells into an array.
(anArray.insert("", at: indexPath)
Since i am not getting indexPath, everything fails. How can i get the indexPath and get the touch on to the textbox?
I am thinking of something like a function that takes the touch ,gets the indexPath and then passes the control to textbox.
Things i have tried.
I disabled the textboxes before user touches the cell (and makes textboxes disabled once user deselects the cell, so cell takes the touch. Once didselectrowat gets called, make the textbox active again and make
textbox.becomeFirstResponder()
But somehow , the textbox never becomes the first responder even though breakpoint shows the control going through it and the textbox becomes active. But no keyboard popsup, if i touch the cell again, same process happens.
What seems to be the issue here? I saw another post on the same topic, i tried it but unfortunately that doesnt work and it was for a static tableview.
Also is there a good way to do this? Other than making the user click on the cell twice / clicking outside the textbox..
You can set your custom cell as delegate for UITextField and use a callback for editing begins/ends as below,
class MyCustomCell: UITableViewCell, UITextFieldDelegate {
public var editCallback: (() -> Void)?
/// Set 'textField.delegate = self' on initialization.
func textFieldDidBeginEditing(_ textField: UITextField) {
self.editCallback?()
}
}
And use the callback in cellForRowAt as,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = MyCustomCell()
cell.editCallback = { [weak self] in
print(indexPath)
}
return cell
}
you can try this
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
//your code here
}

Table View Scrolling Causes Unexpected Results [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
My table view has a hidden image and when the user completes the level, this image becomes visible for the relevant cell. This process works with no issue.
Strangely, when i scroll the table view up and down, this hidden image begins randomly to appear on the other cells which belong to an incompleted level.
If I leave the view controller and get back, unexpected ones dissappear and if I start scrolling again, they come back.
Additionally, if all images are hidden (means there's no completed level), scrolling doesn't cause this issue. Here's the code piece I use:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell") as! CustomTableViewCell
cell.cellView.layer.cornerRadius = cell.cellView.frame.height / 2
cell.levelLabel.text = levels[indexPath.row]
cell.lockingImage.image = UIImage(named: lockState[indexPath.row])
if completeState[indexPath.row] == "true" {
cell.completedImage.isHidden = false
}
return cell
}
Any idea?
Let's say you are doing:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! MyTableViewCell
cell.myImageView.isHidden = true
return cell
}
What you should do is:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! MyTableViewCell
if levels[indexPath.row].isLevelCompleted {
cell.myImageView.isHidden = false
} else {
cell.myImageView.isHidden = true
}
return cell
}
This is because you are dequeuing the cell. Which means UITableView will use old cells. If you change the cell actively, you are good to go.
You probably did not reset the image visibility to false in the prepareForReuse function of the cells, which leads to the image to be visible whenever the cell in question is reused.

UITableViewController, cells are reloading incorrectly

On my app, once I tap to open all my cells they are all loaded on function by the tableView delegated method:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> MyClassName {...}
So every time the cells are loaded, this method is called.
By the first time it loads properly (all cells with black background)
When I go down with the screen and it loads some different cells it also follows my code correctly and loads the cells with white background.
The problem happens when I go back to the top.
Its like the number of white background cells are brought up, make the cells once black backgrounded to become white ones (and that's not what I wanted). I thought that once the cells are loaded in the screen, it should stay on device's memory.
I've put some prints on my code to check if they are incorrect but apparently they are working properly.
So I ask you, did any of you had this kind of problem or a similar one? Do you think this is an iOS bug?
EDITED, ADDED CODE:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> HistoricoSelectedCell {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "historicoCell", for: indexPath) as! HistoricoSelectedCell
let item = itemChosen[indexPath.row].item
let cell = self.configureCell(cell: cell2, indexPath: indexPath, item: item!)
return cell
}
It is a cell re-use issue.
You generate a new cell to use in func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell by calling tableView.dequeueReusableCell(withIdentifier: <identifier string>, for: indexPath) I presume (you really need to post code with your question).
The cell that you get is reused, as in it is not instantiated from scratch but has already been created and used for other cells.
Your options are to:
1) Set all the necessary properties in the cellForRowAt indexPath method.
2) Create a fund configure(cell: UITableViewCell) function that sets the appropriate properties
3) Override prepareForReuse() in your UITableViewClass and restore your properties there.

How to save the state of UITableViewCell accessory checkmark in Swift 3

I have a table view and I would like the user to select only one item from the table view, then I want to add a checkmark to the cell. At the same time, I also want the checkmark on other cells to disappear so the. user can only select one at a time. Then I want to save the data (preferably using UserDefaults). How do I do that?
Create a class variable of type IndexPath. In your cellForRowAt method set .checkmark accessory type only if index path matches the class variable and .none otherwise. In didSelectRowAt method update the indexPath of selected variable and just reload the tableview
you should Use in this way
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let sgp : UITableViewCell = tableView.cellForRow(at: indexPath)!
sgp.accessoryType = .checkmark
}