When adding a checkmark to selected table cells, im seeing check appear in other cells also.
my didSelectRowAtIndexPathCode is:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *player = [squadListArray objectAtIndex:indexPath.row];
NSString *playerName = [player valueForKey:#"fullName"];
NSLog(#"%#", playerName);
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
The NSLog has expect results, only showing the one selection.
Any ideas? Do you need me to show any other code?
Thanks
In your cellForRowAtIndexPath you can't be configuring the cell properly when the cell gets reused. You should always be setting (and resetting) all of the properties of the cell from your data model.
You must have a data model that is being used to tell the table view how many rows it has and what each cell should look like. During didSelectRowAtIndexPath you should be updating your data model with the selected information. Then, in cellForRowAtIndexPath, you can use the information in the data model to decide if the cell has a checkmark or not. If it does you add it, if it doesn't you explicitly remove it (to prevent it being left there if the cell was reused).
Your cell is being recycled by other rows. In the method, cellforrowatindexpath, add the following line at the end:
selectedCell.accessoryType = UITableViewCellAccessoryNone;
Cells are cached and re-used. You need to only save the fact you were selected (maybe in PFObject) and then set the accessory each time you configure a cell.
You need to explicitly tell that you don't want other cells to have the checkmark.
if ([self shouldSelectCell]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
You could try doing the following:
Create NSMutableSet that holds the indexes of selected cells.
#property(strong, nonatomic) NSMutableSet *selectedCells;
-(NSMutableSet *)selectedCells{
if(_selectedCells){
return _selectedCells;
}
_selectedCells = [[NSMutableSet alloc]init];
return _selectedCells;
}
On didSelect update the set and select the cell:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedCells addObject:indexPath];
[tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
Remove the indexPath on didDEselect
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedCells removeObject:indexPath];
}
Inside the
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
update the cell as:
if([self.selectedCells containsObject:indexPath]){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
Related
This question already has answers here:
iOS UITableViewCellAccessoryCheckmark Visible ob every scroll
(4 answers)
Closed 6 years ago.
I've tried every single option available on this website for this problem but none of them seems to be working.
If I scroll down I see the checkmark. If I scroll back up the positioning of my selection is not the same.So as the problem is the same I wanted to open this question for one more time as a fresh start. Here is how I'm doing it:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
myTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (![selectedDX containsObject:myMutArray[indexPath.row]])
{
[selectedDX addObject:myMutArray[indexPath.row]];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
myTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedDX containsObject:myMutArray[indexPath.row]]) {
[selectedDX removeObject:myMutArray[indexPath.row]];
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
I've also tried it in in a single didSelectRowAtIndexPath method but the result is same.
Do you set the accessory type correctly when you return the cell in cellForRowAtIndexPath? It looks to me that you only set the accessory when the user taps on a cell but this is not enough.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[...]
if ([selectedDX containsObject:myMutArray[indexPath.row]])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
[...]
}
Your cells are reused when you scroll in your table view. So one cell is reused for more than one of your items. This means the accessory is also reused. So when you scroll and don't remove the accessory from the cell it will still have the checkmark.
You could also reset the accessory in the prepareForReuse method in a custom UITableViewCell subclass
Add condition in cellForRowAtIndexPath
if([selectedDX containsObject:allCodeLabel[indexPath.row]])
{
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
}
else
{
cell.accessoryType = UITableViewCellAccessoryType.None
}
It works for me.Hope it helps :)
you can handle it like this:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
WCategoriesTableViewCell* cell = [tableView
cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
}
I'm trying to make the selected cell (of a custom UITableViewCell) to have a checkmark on it. I tried the following code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CategorieCell *customCell = [tableView dequeueReusableCellWithIdentifier:#"cellID" forIndexPath:indexPath];
if (customCell.accessoryType == UITableViewCellAccessoryDisclosureIndicator) {
customCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
customCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
But when I selected a cell, nothing happened.
Your mistake is that you dequeue a new custom cell. Instead, you have to find out the cell that actually is selected. Change the first line to:
CategorieCell *customCell = (CategorieCell *)[tableView cellForRowAtIndexPath:indexPath];
This should be it.
In my UITableView called _selectAttributes I want to put and remove a checkmark when I tap on each cell.
This is the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [_selectAttributes cellForRowAtIndexPath:indexPath];
if (cell.accessoryType != UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
Everything seems to work well, but when I scroll up and down the table, checkmarks appear on other cells and disappear on the previous ones.
How can I solve?
Thank you in advance.
Declare an NSIndexPath property named selectedIndexPath.
Then have your delegate methods cellForRowAtIndexPath and didSelectRowAtIndexPath like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if ([indexPath isEqual:self.selectedIndexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:self.selectedIndexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
self.selectedIndexPath = indexPath;
}
UPDATE:
I wasn't paying attention that you want solution for multiple cell selection. My answer obviously solves problem only for single cell selection, but I believe its a good start.
I would create an NSArray of selected index paths. On tableView:didSelectRowAtIndexPath:, add the index path to that array and in tableView:cellForRowAtIndexPath: check whether the index path is in the array and set the UITableViewCell's accessory type accordingly.
I have a list which I have using as a check boxes. I have enable or disable Check mark on row on select. But when I scroll the list its make mark row after every 10 rows.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:indexPath];
if (oldCell.accessoryType == UITableViewCellAccessoryCheckmark)
{
oldCell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
oldCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
UItableView reuses the cell in every scroll so using condition as per accessory type is not a good practice. You can Create an NSMutableArray with selected items and Check as per the Condition below.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if ([selected containsIndex:indexPath.row]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
// Do the rest of your code
return cell;
}
in didSelectrowAtindexpath method you can Add and remove the Selected items.
Its because UITableView reuses the cell.
So, in the method cellForRowAtIndexPath, you will have to check for a particular cell (of a particular section and row), if it needs to be checked on, provide the accessory type.
If not needed for that cell, provide accessory type as none.
You need to put your logic to set accessory type for cell in cellForRowAtIndexPath, and to identify the cell to mark with check mark you can mark the object in the list in didSelectRowAtIndexPath: or manage an array of selected/unselected objects of the list here.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[NSMutableArray addObject:[AnotherMutableArray objectAtIndex:indexPath.row]];
} else {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[NSMutableArray removeObject:[AnotherMutableArray objectAtIndex:indexPath.row]];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
Also in your viewDidLoad, instantiate you both mutable arrays-
yourmutableArray1 = [[NSMutableArray alloc]init];
yourmutableArray2 = [[NSMutableArray alloc]init];
I am an iOS newbie. I am using a checkmark to in a UITableView, and storing the checked value in a local database. When I load the app for the first time, I want to set the value of the checkmark depending on which value exists in the db. How would I do that? Presently this is what I do -
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
if ([indexPath compare:self.lastIndexPath] == NSOrderedSame)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Set up the cell...
NSString *cellValue = [[self countryNames] objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
and then in didSelectRowAtIndexPath -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// some stuff
self.lastIndexPath = indexPath;
[tableView reloadData];
}
Are you asking simply how and when to set the checkmark or are you asking how to populate a table from a database (eg Core Data)?
From your code, the only data you represent is in [self countryNames] and it's not clear under what circumstances you'd want the cell to display a checkmark. Whatever that is, just check the condition and set the checkmark when you are configuring your cell for data (after your "Set up the cell..." comment).
Example if you stored the users country and checked that cell:
// get the current country name
NSString *cellValue = [[self countryNames] objectAtIndex:indexPath.row];
// configure the cell
cell.textLLabel.text = cellValue;
UITableViewCellAccessoryType accessory = UITableViewCellAccessoryNone;
if ([cellValue isEqualToString:self.usersCountry]) {
accessory = UITableViewCellAccessoryCheckmark;
}
cell.accessoryType = accessory;
If you have static table data, then you simply need to store the section and row of the selected table view cell. If you have dynamic data, then you will need to store the unique data for that selected cell in the database and compare that with the cell's content on load. When you are loading your cells in cellForRowAtIndexPath:, simply set that cell's accessory to UITableViewCellAccessoryCheckmark as well as set self.lastIndexPath = indexPath for comparison later.
Also, I typically use [indexPath isEqual:self.lastIndexPath] instead of compare:. Doesn't really make a difference either way, just for readability.