Why repeated cells show up in UITableView? - ios

Now why would repeated cells show up in a UITableView ?
As you can see in this GIF, I press on a cell button to do some fade effect, but other cell gets affected too !
https://media.giphy.com/media/xT0BKL5KnCgEjaXm9i/giphy.gif
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return numberOfCells
}
and the count of cells is always 10
numberOfCells = 10
I always make tableviews and I'm sure of the setup, is this a bug by apple's side?
EDIT :
How the cells get created:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("brandCell", forIndexPath:indexPath) as! CustomCell1INF
cell.selectionStyle = UITableViewCellSelectionStyle.None
cell.frame = self.view.frame
return cell
}

This happens because the UITableViewCell are being reused.
You changed the cell when you press the button, you need to keep track of that in your data source model.
In cellForRowAtIndexPath you have to add a condition to check if that button was pressed or not, then you display the appropriate view accordingly.

Related

UITableView bug? incorrect reusable cells

I have default UITableViewController with 10 row
have UITableViewCell with segment control
If I change segmentController selected index in probably cell : 2, then scroll down this state of segmentController will be in other cells
cells1(selectedIndex: 1 )
cells2(selectedIndex: 1 )
cells3(selectedIndex: 1 )
cells4(selectedIndex: 1 )
cells5(selectedIndex: 1 )
... Select in cell 2 other index (2)
scroll down
and cell 5 have same selected index, but I am not touch them
cells1(selectedIndex: 1 )
cells2(selectedIndex: 2 )
cells3(selectedIndex: 1 )
cells4(selectedIndex: 1 )
cells5(selectedIndex: 2 )
selected 0 row
row 5 is too selected, why?
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.selectionStyle = .none
cell.textLabel?.text = String(indexPath.row)
cell.textLabel?.textColor = .white
return cell
}
UITableView and UICollectionView reuse cells. Which means it only keeps enough cells in memory to show what is on the screen. As you scroll cells off the screen they are fed back in to become the cells that are appearing. You need to properly configure the cells as they re-appear in your override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
So in your case you need to set the segmented control's selection in cellForRow every time.
This means you will need a way to keep track of what selection has been made on your segmented controls and call that up to set the segmented control correctly when the cell is being shown again.
Reset selection in prepareForReuse method of UITableViewCell by subclassing it.
override func prepareForReuse() {
}

UITableView left margin checkmark buttons - Swift

I'm trying to add check marks to my UItableview cells. I want to checkmarks to display like circle buttons on the left margin like this image:
I am unable to get the checkmarks in the left margin with my code and instead I keep getting checkmarks on the right that display only when tapped. Here is my current code:
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .None
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .Checkmark
}
}
Any idea on how i can get the checkmarks to display on the left like the image?
I've made for you whole sample application for this.
just try this.
And this is what it looks like.

UITableViewCells invisible

Requirement :
I have a list of UITableviewCell loaded from a nib that I'm presenting on UITableview. The first time I open the UIViewController all cells are shown correctly and work as expected.
Issue :
If I navigate back to the parent and then open the UIViewController again the UITableviewCell are 'invisible'. I say invisible because with a breakpoint in cellForRowAt I can see that the table view does load all cells and the cells are valid.
Code :
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 13
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 40
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = (project?.sliderData.sliders[indexPath.row].view)! as UITableViewCell
print(cell.contentView.subviews.count)
if let left = cell.viewWithTag(2) as? UILabel {
left.text = "left"
}
if let middle = cell.viewWithTag(3) as? UILabel {
middle.text = "middle"
}
if let right = cell.viewWithTag(4) as? UILabel {
right.text = "right"
}
return cell
}
Screen Shot Image
Expected observation :
I was thinking that maybe the subviews of the cells get released because I don't have any bindings to them in IB. To test this I'm printing the count of subviews and writing some text to the subview labels. And everything seems to go fine, the cells are loaded and the labels are there but the cells just don't show up.
But then, if I scroll the TableView up and down a little to get some cells updated those cells do appear at the top and bottom of the view as shown in the pic.
You need to call dequeueReusableCell(withIdentifier: "cell") inside your code then will show your table cell. It will reuse cell for your all numbers of row data content.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! UITableViewCell
return cell
}
More Details : How to create uitableview with multiple sections in iOS Swift.
Did not find reason why the tableView behaves the way it does so I solved the issue by dequeueing default cells. The views provided by the slider objects are added as subviews to the dequeued cells. Now the subviews can of course be any UIViews.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "sliderCell")
if cell == nil {
cell = UITableViewCell.init(style: .default, reuseIdentifier: "sliderCell")
}
cell?.addSubview((project?.sliderData.sliders[indexPath.row].view)!)
return cell!
}

didSelectRowAtIndexPath returns wrong row index inconsistently

I have a table view with rows, and when clicking on the row, sometimes it returns the row that is up one position from the one I clicked. The relevant code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCell: UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!
currentCell.backgroundColor = UIColor.greenColor()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")!
//.... cell modifications
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// this is to make at least one empty row
if (meeting.attendees.isEmpty) {
return 1
} else {
if section == 0 {
return requiredParticipants.count }
else {
return optionalParticipants.count }
}
}
What did I do to address the issue:
1. checked the consistency of arrays with the numberOfRows function (it's correct, the number is right)
2. checked the height of the cell - suspected the upper cell to overlap somehow the bottom cell - also not the case
3. refactored cellForRow to use dequeReusableCell (was not used initially) - suspected the memory issue, also did not help.
What happens: when you click, the cell that is clicked is highlighted with the green light, and approx. 50% of the time, the cell one position up from the one you click gets highlighted. The issue is also inconsistent, meaning that half of the time the right one is highlighted.

Wrap Text in UITableView Custom Cell When It Reaches End of Screen (Swift)

I have a table that loads data from a database but the problem is if the text being loaded is too long, it goes off the screen. I'm trying to find a way for the text to go onto the next line and have the cell resize automatically to fit this change. Does anyone know how this is done? The cell has three labels but one of them is allowed to be multi-lined.
EDIT:
I got it to work using auto constraints but how can I resize the table cell so that the actual items fit inside the cell and do not go over the cell boundary?
Set label number of "Lines" to ZERO. And set "Line Breaks" to "Word Wrap"
Adding these two methods along with above code fixed the problem with custom font
tamilRow.textLabel?.numberOfLines=0
tamilRow.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
func tableView(tableView: UITableView, heightForRowAtIndexPath
indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
swift 5
let unselectedCellHeight: CGFloat = 130.0
func tableView(_: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if selectedCellIndexPath == indexPath {
//return selectedCellHeight
return UITableView.automaticDimension
}
return unselectedCellHeight
}

Resources