UITableViewController, cells are reloading incorrectly - swift

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.

Related

How to show separate View(box) in between tableview in Swift

In this screen how to show (blue view) in between tableview rows
design image
code: in storyboard design i have given all static data in labels and images so with this below code i am getting all cells like above screen shot, but after three cells how to show blue box view, please suggest me
import UIKit
class ViewController: UIViewController , UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BidCell", for: indexPath)
return cell
}
There are two ways to do that:
Use a different UITableViewCell class (probably what you are looking for?)
Use sections
How?
You can either create a new UITableViewCell prototype cell in your storyboard or do it programmatically.
Create a custom UITableViewCell as such:
class OfferTableViewCell: UITableViewCell {
}
// If you are not using storyboards, add the following code
// in your viewDidLoad
tableView.register(OfferTableViewCell.self, forCellReuseIdentifier: "your_cell_id")
Then, you can dequeue the newly created cell at any index as such:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 10 // Index of the different cell
let cell = tableView.dequeueReusableCell(withIdentifier: "your_cell_id", for: indexPath) as! OfferTableViewCell
// Do cell configuration here
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "BidCell", for: indexPath)
return cell
}
}
Keep in mind that this cell is going to take the place of another cell if you are using an array as datasource, so using myArray.count for your numberOfRowsInSection would result in the last array element missing. You will have to take that into account.
Resources
Using multiple custom cells in a TableView
UITableView sections
Custom header for TableView sections

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
}

Xcode static cells with dynamic backgroundColor

Is there a possibility to set a dynamic backgroundColor with static cells in a UITableView?
For example the user pressed a button in a UITableView and then all cells in the same view change to a specific color.
I already figured out how to set a backgroundColor when the view shows up:
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.backgroundColor = UIColor.black
}
Now I want to achieve the same when the view has already loaded. Any suggestions?
You can access the currently visible cells (the ones that have passed over the willDisplay milestone) via the visibleCells property. You can iterate over this array and do whatever you need:
for cell in tableView.visibleCells {
cell.backgroundColor = UIColor.black
}
Alternatively you can call reloadData() on the tableView, this will result in all cells being re-created and re-displayed.
You can use a delegate method called DidSelect this method works when a user tap on a cell in the tableView or inside an element, and returns the index path of selected Cell you can use that to edit background color or anything.
The code should be something like this optional func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) inside this function you can get the cell using cellForRowAtIndexPath and pass it the selected path and cast it as the cell type you have and then edit it or do whatever.
The full code would look something like this
optional func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath){
let cell = tableView.cellForRow(at: indexPath)
//use the cell object and do what you want
}

IOS swift how can I create a small horizontal line inside a tableView cell

I have a tableView UI and I would like to create a small horizontal line below a certain field inside the TableViewCell for instance this is how it looks, I would like to make the horizontal line right below the Location: Atlanta, GA . This is how the main storyboard looks . I just want to create a thin gray horizontal line below the location field in the prototype cell . Any suggestions would be great . I have found a way to create a line but it was essentially to create a border at the end of the TableCell which is not what I need.
Emulator Image
ProtoType Cell
My code for the TableView is as follows
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let mycell = self.StreamsTableView.dequeueReusableCell(withIdentifier: "prototype1", for: indexPath) as! HomePage_TableViewCell
return mycell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
tableView.backgroundColor = UIColor.clear
return names.count
}
You can do this from the Xcode interface builder by adding a View (UIView) control and set the height to 1.