Reputation: 39
Edit: Added an else statement to remove the checkmark. However, now, it doesn't repeat the checkmarks anymore, but if two or more cells are marked and I scroll down and back up, it removes all of them except one. Any ideas why? I am having a hard time understanding cell recycling, when this happens.
I've been pulling my hair out at this problem, as I am just not able to figure it out. Any pointers or help would be greatly appreciated.
Everytime I choose a cell and scroll, it repeats the checkmark randomly. I am deciding if a cell needs a checkmark, by checking the indexPath.row with an array that contains the indexPath.row + 1.
Updating the titles and descriptions when scrolling works just fine, it's just the checkmarks that are acting up.
This is my current code for cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = @"KnuterItem";
if([s.taskArray valueForKey:@"TaskData"] != [NSNull null])
{
KJBasicCell *cell = (KJBasicCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
// Add utility buttons
NSMutableArray *rightUtilityButtons = [NSMutableArray new];
[rightUtilityButtons sw_addUtilityButtonWithColor:
[UIColor colorWithRed:1.0f green:0.231f blue:0.188 alpha:1.0f]
title:@"Les mer"];
cell.rightUtilityButtons = rightUtilityButtons;
cell.delegate = self;
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"KnuterItem" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *item = [s.taskArray objectAtIndex:indexPath.row];
if([item objectForKey:@"Title"] != [NSNull null])
cell.titleLabel.text = [item objectForKey:@"Title"];
if(s.textColor)
cell.titleLabel.textColor = s.textColor;
if([item objectForKey:@"Description"] != [NSNull null]){
if (s.isNotAutoRowHeight == 0) {
cell.descLabel.numberOfLines = 0;
} else {
cell.descLabel.numberOfLines = 1;
}
cell.descLabel.text = [item objectForKey:@"Description"];
if(s.textColor)
cell.descLabel.textColor = s.textColor;
cell.descriptionText = [item objectForKey:@"Description"];
}
if([[s.selfArray valueForKey:@"CheckStat"] isEqualToString:@"(null)"])
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
else if([[s.selfArray valueForKey:@"CheckStat"] length] == 0)
{
if ([[item objectForKey:@"CheckStat"] containsString:@"1"])
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
NSLog(@"array: %@", [s.selfArray valueForKey:@"CheckStat"]);
for(int i = 0; i < [[[s.selfArray valueForKey:@"CheckStat"] componentsSeparatedByString:@","] count]; i++)
{
NSString *checkedNumStr = [[[s.selfArray valueForKey:@"CheckStat"] componentsSeparatedByString:@","] objectAtIndex:i];
if ([checkedNumStr intValue] == indexPath.row + 1)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
return cell;
}
else
return nil;
}
didSelectRowAtIndex:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
CheckStatStr = nil;
for(int i = 0; i < [s.taskArray count]; i++)
{
NSIndexPath *eachPath = [NSIndexPath indexPathForRow:i inSection:0] ;
UITableViewCell *eachCell = [tableView cellForRowAtIndexPath:eachPath];
if(eachCell.accessoryType == UITableViewCellAccessoryCheckmark)
{
if([CheckStatStr length] == 0 || !CheckStatStr)
{
CheckStatStr = [[NSMutableString alloc] init];
[CheckStatStr setString:(NSString*)[NSString stringWithFormat:@"%d",i+1]];
}
else
[CheckStatStr appendString:[NSString stringWithFormat:@",%d",i+1]];
}
}
if(CheckStatStr){
s.OldCheckStatStr = [s.selfArray valueForKey:@"CheckStat"];
[s.selfArray setValue:CheckStatStr forKey:@"CheckStat"];
}else{
[s.selfArray setValue:@"0" forKey:@"CheckStat"];
}
}
Upvotes: 0
Views: 1204
Reputation: 1754
How I solve This Issue in Swift 5
Main Reason of repeating checkmark is cell reusable . then displaying cell resuse and checkmark Still Apear . How I resolve this issue :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.schedulTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
as! scheduleCell
cell.timeLable.text = self.timeArray[indexPath.row]
// here is the code which clear checkmark on reuse
if item.num >= 0 && item.isSelected == true{
if item.num == indexPath.row{
cell.accessoryType = .checkmark
}else{
cell.accessoryType = .none
}
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selected_Time = self.timeArray[indexPath.row]
item.isSelected = true
item.num = indexPath.row
schedulTable.cellForRow(at: indexPath)?.accessoryType = .checkmark
//schedulTable.reloadData()
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
schedulTable.cellForRow(at: indexPath)?.accessoryType = .none
}
struct Item {
var num : Int
var isSelected : Bool
init() {
num = -1
isSelected = false
}}
Upvotes: 0
Reputation: 56
With Swift 3.0,
cell.accessoryType = UITableViewCellAccessoryNone;
becomes
`cell.accessoryType = UITableViewCellAccessoryType.none
Upvotes: 0
Reputation: 2251
Another cause of this is if there's any layer backed effects (i.e. animations)... Click on the CB itself and pop open the "View effects inspector".. In there you should see a list of CA (core animation) layers..
If you've toyed with the rendering of the CB's then, I'd suggest you either look in there and enable the correct layers, or reconnect the badly rendered rendition :D
Upvotes: 0
Reputation: 5536
Without looking at the source, I can tell you are a victim of cell recycling. Apple does this for performance reasons, make sure that you deselect the cell in tableView:cellForRowAtIndexPath:
(remove the checkmark) if it shouldn't be checked, otherwise it will retain the checkmark when recycling another cell.
cell.accessoryType = UITableViewCellAccessoryNone
Edit with more code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
s.taskArray[indexPath.row][@"CheckStat"] = @YES
}
Upvotes: 0
Reputation: 9825
When you check if ([checkedNumStr intValue] == indexPath.row + 1)
and set add the checkmark, you need to set cell.accessoryType = UITableViewCellAccessoryNone
if it isn't.
if ([checkedNumStr intValue] == indexPath.row + 1)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
Table view cells get reused, so if a cell that has a checkmark is reused for a row that you don't want to have a checkmark you need to remove the checkmark.
Upvotes: 2