How to keep tablecells from inheritiing in Swift - swift

I'm trying to generate cells in my table view, each with dynamically allowed buttons on the right-hand side; some with 2 buttons, some with 4 buttons. The problem is, though the table view loads as I'd like, upon scrolling around, the cells end up all having 4 buttons - even the ones that only had two before hand.
What am I doing wrong?
Here is my code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row][0]
cell.accessibilityLabel = self.items[indexPath.row][bigSort]
cell.selectionStyle = .None
for x in 0..<4
{
let button = UIButton()
let marginStart = w - tickWidthInCell * 4 - 9 + (tickWidthInCell + 2) * x
let margin = CGFloat(marginStart)
button.frame = CGRectMake(margin, CGFloat(cellHeightMargin), CGFloat(tickWidthInCell), CGFloat(tickHeightInCell))
button.layer.borderColor = GRAY.CGColor
if (self.items[indexPath.row][1] == "Special" && x % 2 != 0)
{
button.backgroundColor = UIColor.clearColor()
button.layer.borderColor = UIColor.clearColor().CGColor
//button.hidden = true
}
else
{
button.addTarget(self, action: #selector(cellButtonClicked), forControlEvents: .TouchUpInside)
button.backgroundColor = UIColor(netHex:0x222222)
button.layer.borderWidth = 1
}
cell.contentView.addSubview(button)
}
return cell
}

It's because tableview reuses the cells you define.
To get control over how the reusing should happen, in your custom UITableViewCell override prepareForReuse. And always reset them the state you want to be, like setting the cell to only have 2 buttons)
Or in cellForRowAtIndexPath you can handle both cases to have either 2 buttons or 4.
(when you are specifying that you want 2 buttons make sure that you hide the other 2)

Related

UITableViewCell style goes away after scrolling down

I am trying to figure out why my custom styling for table cells disappears after scrolling down in a table view and them back up. What do I need to do to have the style persist?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : CustomTrendingCell = trendingTableView.dequeueReusableCell(withIdentifier: "cell") as! CustomTrendingCell
cell.selectionStyle = .none
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(searchForTrendingTerm(sender:)))
cell.iconView_search.isUserInteractionEnabled = true
cell.iconView_search.tag = indexPath.row
cell.iconView_search.addGestureRecognizer(tapGesture)
cell.trendingLabel.text = trendingSearchTerms[indexPath.row]
cell.elevate(elevation: 4.0) //where my style is being set
return cell
}
extension UIView {
func elevate(elevation: Double) {
self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: elevation)
self.layer.shadowRadius = abs(CGFloat(elevation))
self.layer.shadowOpacity = 0.4
}
}
The top 2 items in the screenshot below have been scrolled down and up. The drop shadow styling has been removed. The bottom 2 have the correct styling and have not been scrolled down.
Screenshot example
One possible solution here is to explicitly specify the zPosition of each cell's layer.
You would want to ensure that the upper cell has the higher position so that it's content (shadow) lies over the lower cell.
In your cell for row at function add:
cell.layer.zPosition = CGFloat(numberOfRows - indexPath.row)

how to save the action of a button press inside of a cell, so that I can add an image without it duplicating or disappearing

I have a tableViewController that has three functions, two of which are working successfully.
Add cells by pressing button inside of toolbar = works
Being able to insert text into UITextView inside of cell, without the text duplicating and moving around = works
When button in cell is pressed, checkMarkImage appears, without getting duplicated when scrolling and moving around = does not work
The checkMarkImage does not stay put at the cell in which the button is pressed. It reappears when scrolling and sometimes disappears, despite my efforts of using a Boolean value, in order to track the cells of which have been checkmarked.
the configuration of the button inside of the my customCellClass:
#IBAction func checkMarkButton(_ sender: UIButton) {
if checkedOff{
UIImageView.animate(withDuration: 0.3, delay: 0, options: [], animations: {
self.checkMarkImage.alpha = 0.0
self.notesTextView.isEditable = true
self.notesTextView.textColor = .white
self.checkedOff = false
},completion: nil)
}
else{
UIImageView.animate(withDuration: 0.3, delay: 0, options: [], animations: {
self.checkMarkImage.alpha = 1.0
self.notesTextView.isEditable = false
self.notesTextView.textColor = .orange
self.checkedOff = true
}, completion: nil)
}
}
The handling of cell inside cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "TableViewNotesCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! TableViewNotesCell
cell.notesTextView.text = cellNumber[indexPath.row]
if cellNumber[indexPath.row] < " "{
print("celltext is less than nothing")
cell.notesTextView.textColor = .white
cell.notesTextView.isEditable = true
cell.checkMarkImage.alpha = 0.0
}
else{
if cell.checkedOff{
print("cell has been checked off")
cell.notesTextView.textColor = .orange
cell.notesTextView.isEditable = false
cell.checkMarkImage.alpha = 1.0
}
}
My expect the cell's checkMarkImage to stay at the cell in which the button is pressed, but the actual effect is that the checkMarkImage is re-occurring, when scrolling, and sometimes completely disappears
I am afraid that by doing this you not gonna achieve the desired outcome.
you must persist your data when you using UITableView or UICollectionView because these reuse the Cell when scrolling. so when you scroll the UITableView you are getting duplicate image or sometime loosing it. what you can do is :
Use an array of dictionary as dataSource to persist your data for the TableView.
you can also create your own model and use as the dataSource of TableView.
and if your data is large enough then you can go for CoreData / Sqllight.

swift tableview cell change width frame not work

This is my code but not work!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyChatCell
var frame = cell.frame
if(indexPath%2 == 0){
frame.size.width = CGFloat(200)
} else {
frame.size.width = CGFloat(100)
}
cell.frame = frame
return cell
}
I want change cell width to 100 or 200 per cell
But frame.size.width not work
You can't change that, because all cells in a table view must have the same width, but can have different heights if needed.
However, you can try to make the table view's .backgroundColor transparent, and maybe the content view of the cell, than add another "wrapper view" on the cell's content view and make it have different widths. It will create the "visual impression" that cells indeed have different widths.

TableView every other cell one color

Is there a way to color every other cell one color on a tableView? I tried looking into the properties for my tableView but were not able to find anything.
I want it like this:
tableview
cell - white
cell - gray
cell - white
cell - gray
etc...
One line code, if you want
cell.backgroundColor = indexPath.row % 2 == 0 ? .white : .gray
The easiest way will be to do this programmatically in your cellForRowAt function:
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor.white
} else {
cell.backgroundColor = UIColor.gray
}

inaccurate data returned to swift button while scrolling

I hope I am giving enough information by just showing the "cellForRowAtIndexPath" segment. The entire program is too long. Each row in my tableView represents a player and each player has four buttons associated with him/her. Based on an action of the player, I will press one of the buttons to record that action and keep a tally for each of the button presses in the titleLabel of that button. I have created an array for each button to keep track of the number of button presses in each of the buttons, "plyZeroes", "plrOnes", "plrTwoes", and "plrThrees". I use these arrays (plrZeroesArray, plyrOnesArray, etc) to save the correct value and then reload the button titleLabel with this correct value just before it it is redisplayed (in the event it has scrolled off the screen and then reappear). At least that's what I think I am doing. But it may be my lack of understanding of how cellForRowAtIndexPath works.
In the code segment below I have set breakpoints and have placed "print" statements at various places and I am confident that the array has assigned the correct information to each one of the "plrxxx" buttons just before the "return cell" statement. However, when I run the application and if I scroll the device (iPad) enough, the count (text of the label) shown on the device is different than the value in the array (different than the value that was assigned to the button's textLabel). If I scroll again to show the cell, the values become correct. Basically when some cells disappear and reappear, the contain incorrect values about 30%- 50% of the time. Any ideas?
ps: there is another object "plrAvg" that is a label and I do the same saving of the data before it is returned, and it works fine all the time.
var plrNumbers: NSMutableArray! = NSMutableArray()
var players: NSMutableArray! = NSMutableArray()
var plrAverageArray = [String](count: 99, repeatedValue: "0")
var plrZeroesArray = [String](count: 99, repeatedValue: "0")
var plrOnesArray = [String](count: 99, repeatedValue: "0")
var plrTwosArray = [String](count: 99, repeatedValue: "0")
var plrThreesArray = [String](count: 99, repeatedValue: "0")
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomCell
// Poputate the players' info, average, and last action//
cell.hiddenLabel.text = ("\(indexPath.row)")
cell.plrNumbers.text = (plrNumbers[indexPath.row] as! String)
cell.plrNames.text = (players[indexPath.row] as! String)
cell.plrZeroes.addTarget(self, action: "handleButtonPressed:", forControlEvents: .TouchUpInside)
cell.plrOnes.addTarget(self, action: "handleButtonPressed:", forControlEvents: .TouchUpInside)
cell.plrTwos.addTarget(self, action: "handleButtonPressed:", forControlEvents: .TouchUpInside)
cell.plrThrees.addTarget(self, action: "handleButtonPressed:", forControlEvents: .TouchUpInside)
cell.btnUndoLastPlrAction.addTarget(self, action: "handleButtonPressed:", forControlEvents: .TouchUpInside)
//restore the player's average in case it was lost because it scrolled off the screen
cell.plrAvg.text = (plrAverageArray[indexPath.row])
//restore the button text in case it was lost because it scrolled off the screen
cell.plrZeroes.titleLabel?.text = (plrZeroesArray[indexPath.row])
cell.plrOnes.titleLabel?.text = (plrOnesArray[indexPath.row])
cell.plrTwos.titleLabel?.text = (plrTwosArray[indexPath.row])
cell.plrThrees.titleLabel?.text = (plrThreesArray[indexPath.row])
print("Buttons \(indexPath.row)] = ", plrZeroesArray[indexPath.row] + plrOnesArray[indexPath.row] + plrTwosArray[indexPath.row] + plrThreesArray[indexPath.row])
return cell
}