Reputation: 381
So I have a TableView with custom cells that I make from fetching data from a server. I have a variable 'selectedIndex' which I use to keep track and add a checkmark accessory to my cell. Weirdly, it only works after I scroll the selected cell (cell with indexPath.row is equal to off the screen and back. Here is the code in my willDisplayCell method:
if selectedIndex == indexPath.row {
if let accessory = cell.viewWithTag(528) as? UITableViewCell {
accessory.frame = (cell.checkmarkView.bounds.offsetBy(dx: 0, dy: 7))
accessory.accessoryType = .checkmark
accessory.isUserInteractionEnabled = false
accessory.backgroundColor = UIColor.clear
accessory.tag = 528
accessory.isHidden = false
print("accessory not nil")
} else {
let accessory = UITableViewCell()
accessory.frame = (cell.checkmarkView.bounds.offsetBy(dx: 0, dy: 7))
accessory.accessoryType = .checkmark
accessory.isUserInteractionEnabled = false
accessory.backgroundColor = UIColor.clear
accessory.tag = 528
accessory.isHidden = false
cell.addSubview(accessory)
print("accessory nil")
}
} else {
let accessory = cell.viewWithTag(528)
accessory?.isHidden = true
}
For example, when the selected index is 0, the checkmark is not displayed at first view, and the logs print ("accessory nil"). When I scroll the cell at index 0 off-screen, and scroll to it again, the checkmark is now displayed and the logs print ("accessory not nil"). For more information, tapping on a cell works just as expected.
Edit:
I know I'm adding another TableViewCell to my cell! I'm only doing that because I need my checkmark accessory to be in a different position (left-aligned, top-aligned) than the default one (right-aligned, vertically centered). So what I did was add a view in my XIB that is in the desired position (right-aligned, top-aligned) and and aligned my programatically-made cell to it. If you could show me another approach it would be appreciated.
Removed cell.addSubview from the first if. Still behaves the same.
Thanks!
Upvotes: 1
Views: 477
Reputation: 20804
You are adding UITableViewCell
into your dequeued original cell, this is unnecessary, you need implement this logic in your cellForRowAt
datasource method,
If you need a custom position for your accessory view use cell.layoutMargins
check my updated code
try this instead
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellIdentifier", for: indexPath) as! YourCellClass
cell.accessoryType = .none
if selectedIndex == indexPath.row {
cell.accessoryType = .checkmark
}
//if you need a custom position for your accessory view
cell.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 100)
}
Upvotes: 1
Reputation: 350
UITableView
will optimize your cells by reusing them. So in your case it seems better to use tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath)
instead of calling the Cell's constructor yourself or find the cell back by looking for it's tag.
Besides that the part which determines the state of the cell should be in the UITableView
's tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
function instead of the willDisplayCell. This might solve your problem and prevents issues with reusing cells.
Upvotes: 0