I want to change the image in a custom UITableViewCell, depending on whether it is selected or not.
So, when user selects a row, the image in two rows has to be changed (both the current selected and the one to be selected).
Calling reloadData, or reloadRowsAtIndexPaths from didSelectRowAtIndexPath doesn't work because it deselects the current selected row, which I don't want to happen.
Calling reloadData from willDeselectRowAtIndexPath and willSelectRowAtIndexPath also causes the same problem.
Anyone know a solution for this?
Did you try just programmatically selecting the row in cellForRowAtIndexPath based on a stored property indicating the selected row?
I would an approach where you still use reloadData, or reloadRowsAtIndexPaths from didSelectRowAtIndexPath but first save the selected row in a property so that you can manually set it as selected when the cell is redrawn.
For example:
var selectedRow:NSIndexPath? = nil
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath
tableView.reloadData() // or reload a specific row
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TableViewCellReuseIdentifier")
if (indexPath == selectedRow) {
cell!.selected = true
} else {
cell!.selected = false
}
}
Related
I am working on xamarin.ios. I have a UITableView control at my view. I select a row in it and then move to next screen. If I come back to UITableView screen again the selected row doesn't highlight. It highlight for a second and then deselect automatically. How it can be managed if I come back to the tableview, the selected row should be highlighted.
Hard to say without seeing any code, but looks like the tableview is being reloaded in viewDidAppear. You may want to store the selected row index in NSUserDefaults or somewhere else to persist the selection between view loads/appearances.
Make sure you are setting it selected after the tableview reloads as well, using an appropriate delegate method. Again, without any code to look at, it's hard to see where - and which order - you're doing this, but an example (Swift):
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == tableView.numberOfRowsInSection(0) - 1 {
cell.selected = true
}
}
Alternatively, you could set the selected property in your datasource directly, and then you could do:
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
datasource[indexPath.row].selected == true {
cell.selected = true
}
}
If you do it this way, then the selected row will always be set correctly every time the tableview is loaded.
(Full disclosure, I'm not a Xamarin dev, so I'm not sure how those translate from Swift/Obj-C to Xamarin)
I currently have a TableView in my project, which is set up to turn a cell green when it is pressed, and back to clear if it is pressed a second time. However, if I scroll down to the bottom of the table view, and scroll back up, all my cells have been reset to their default clear colour.
I'm not sure how to go about fixing this issue, as anything I can find referring to it is in Objective-C rather than Swift. Any help and advice as to how to go about this would be great, thanks.
Everytime a UITableViewCell goes out of the screen, any function that you've written in the tableViewController/ViewController runs again.
for example in cellForRowAtIndexPath if you have a cell.setUpCell() or something similar, it will rerun and reset your values to the original values.
if you have a
var name = testName in your MainVC
and you update something in your cell, you should change the name in your mainVc too.
Every time you scroll or call tableView.reloadData() UITableView cells will reload. So, every time you select UITableViewCell, add selected index (indexPath.row) to an array(ex: selectedIndexArray) in your didSelectRowAt indexPath: delegate. If the cell you selected is already selected one, then remove the cell from selectedIndexArray.
And in your cellForRowAt indexPath: manage the cells using selectedIndexArray.
var selectedIndexArray:[Int] = [] //to save selected tableViewCells
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let isSelected = false
for each in selectedIndexArray
{
if each == indexPath.row
{
isSelected = true
}
}
if isSelected == true
{
//set selected cell color
}
else
{
//set default cell color
}
}
You need to write the logic of adding and removing cell indexes in your didSelectRowAt indexPath:.
I have a UITableView which has prototype cells which include a slider and a textfield next to it. As the slider's value changes, the value inside the textview is also changed. It works fine except for when the size of the table increases, the new cell generated when scrolling down is already shows the value of the first cell. I do realize that this has something to do with the dequeueReusableCellWithIdentifier function as the cells are reused. How can this be circumvented?
This is the code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("infoCell") as! InfoCell
cell.dressLabel.text = inputArrayFortableView[indexPath.row]
cell.uiSlider.maximumValue = 100
cell.uiSlider.minimumValue = 0
cell.uiSlider.continuous = true
cell.uiSlider.addTarget(cell, action: #selector(cell.uiSliderSetValue), forControlEvents: .ValueChanged)
if(cell.DressTextField.text != "")
{
cell.uiSlider.setValue(Float(cell.DressTextField.text!)!, animated: true)
}
print("outside uisliderSetvalue")
cell.uiSlider.tag = indexPath.row
print(cell.uiSlider.tag)
return cell
}
I am attaching a screenshot. Keep in mind the when I scroll downwards, the new cell has the same value as that of the first one, the second cell generated has the same value as that of the second and so on.
Because cells are reused, the slider will retain the value from the previous time the cell was used. Make sure to always initialize the slider in cellForRowAtIndexPath:
if cell.DressTextField.text != ""
{
cell.uiSlider.setValue(Float(cell.DressTextField.text!)!, animated: true)
} else {
cell.uiSlider.setValue(0, animated: false)
}
You have to store value of slider to inputArrayFortableView when the value is changed. You have to reload this value each time func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell calling because table cells is reuse, it stores old value.
I've got a tableView in the ViewController & an array called toDo, in the TableView I've a cell and in the cell I got textView.
the textView is editable (The user can change the text in the textView).
After the user changes the text - I want the cell to save it to the toDo array, but whenever I reloaddata the text disappears.
Here is what I tried:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: TableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath:indexPath) as! TableViewCell
cell.textField.text = toDo[indexPath.row]
cell.textField.delegate = self
return cell
}
**I have a got a test button that whenever I click it reload data.
Try this out - set the tag on the text field and implement textFieldDidEndEditing: to update your model before reloading the table view.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: TableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath:indexPath) as! TableViewCell
cell.textField.text = toDo[indexPath.row]
cell.textField.tag = indexPath.row
cell.textField.delegate = self
return cell
}
func textFieldDidEndEditing(textField: UITextField) {
toDo[textField.tag] = textField.text
}
I think that the problem is that, whenever the system needs to re-render the cell, the method func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) is called; that happens before your text view has a chance to save its content in the data model. In your case every time you press the button. I assume you save the content of the text field using optional func textFieldDidEndEditing(_ textField: UITextField) delegate method. You can add a println("SAVING") in such method, and a println("RE-RENDERING CELL") in the tableView(...) method and see the what the sequence of events is. Nots sure if this could help, but I would try that.
I have successfully implemented a search function. I want to be able to search my list, select an item on the list, then return to the main tableview while the item remains selected. How do I do this?
This is the tableview without any selections or character typed into the searchbar. Items do not have a detail view. Items do have more information that can be retrieved, e.g. url. This data must be retrieved later when a user presses the "mail" button top left.
This is the list with search results. The grey highlight of the cell indicates that the cell is selected. How do I now return to the main tableview, whilst keeping the selection? I only see the cancel-button top right, the cross-button in the searchbar top middle, and the "search" button on the lower right part of the keyboard. None bring you back to the main tableview whilst storing the selection.
Based on the suggested answers, I was able to store the row's index path, using the function below:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let rowToSelect = indexPath
println(rowToSelect)
selectedCellTitle = selectedCell?.textLabel?.text ?? ""
println("The stored cell is called \(selectedCellTitle)")
}
However, I haven't succeeded in reselecting the row in the main tableview. My code is below. It looks like the constant "rowToSelect" is not carried over to another function (see the one before last line of code). How do I fix this?
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
if tableView == self.searchDisplayController!.searchResultsTableView {
cell.textLabel?.text = filteredPublications[indexPath.row].valueForKey("fullTitle") as? String
cell.detailTextLabel?.text = filteredPublications[indexPath.row].valueForKey("journal") as? String
} else {
cell.textLabel?.text = publications[indexPath.row].valueForKey("fullTitle") as? String
cell.detailTextLabel?.text = publications[indexPath.row].valueForKey("journal") as? String
self.tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: .Top)
}
return cell
}
The UITableView Delegate has a function tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath. This function get’s called when a row is selected.
If you listen for this function and save the selected indexPath, you can use selectRowAtIndexPath to (re)select it in your main view.
Implement this function to listen for any selections made in your tableView
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//get back to your filled UITableView
//Save "indexPath" to a variable
}
When you get back to the view controller where you have your UITableView
self.tlbView.selectRowAtIndexPath(“above declared variable”, animated: true, scrollPosition: .Top)
If you're able to hold the index of the Cell in your tableViewController, you could use self.tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: .Top) as soon as you come back to your tableView. This will keep the cell grey like in your picture even if you scroll the table.