Using BOOL objects in NSMutableArray to determine cell statuses - ios

I'm using an NSMutableArray referenced as 'stateArray'. stateArray needs to simply hold the BOOL value for my cells to determine whether or not they are selected. here's my code..
stateArray in my .h:
#property (nonatomic, strong) NSMutableArray *stateArray;
Then stateArray is not synthesized. It needs to be filled with NO throughout the array, so that when the cell becomes selected, NO can be replaced by YES. Currently this code is printing 0's for stateArray for every cell(the NSLog is in the if (showCheckmark == YES) from my cellForRowAtIndexPath:).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[[UITableViewCell appearance] setTintColor:[UIColor colorWithHexString:#"#669900"]];
#define CHECK_NULL_STRING(str) ([str isKindOfClass:[NSNull class]] || !str)?#"":str
static NSString *CellIdentifier = #"inviteCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//Customization
cell.textLabel.highlightedTextColor = [UIColor colorWithHexString:#"#669900"];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.backgroundColor = [UIColor blackColor];
cell.textLabel.textColor = [UIColor whiteColor];
//Ignore this, it's for UISearchBar
BOOL isSearching = tableView != self.tableView;
NSArray *arrayToUse = (isSearching ? searchResults : contactsObjects);
id p = arrayToUse[indexPath.row];
NSString *fName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByFirstName));
NSString *lName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByLastName));
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", CHECK_NULL_STRING(fName), CHECK_NULL_STRING(lName)];
_stateArray = [NSMutableArray array];
for (int i = 0 ; i != contactsObjects.count ; i++) [_stateArray addObject:#(NO)];
BOOL showCheckmark = [[_stateArray objectAtIndex:indexPath.row] boolValue];
if (showCheckmark == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSLog(#"It hit showCheckmark = YES, and stateArray is %#",_stateArray[indexPath.row]);
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(#"It hit showCheckmark = NO, and stateArray is %#",_stateArray[indexPath.row]);
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
id object = contactsObjects[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[_stateArray replaceObjectAtIndex:indexPath.row withObject:#(YES)];
[selectedObjects addObject:object];
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
[_stateArray replaceObjectAtIndex:indexPath.row withObject:#(NO)];
[selectedObjects removeObject:object];
}
//slow-motion selection animation.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

To keep track on selected items, use a Dictionary instead of NSMutableArray and keep the indexPath.row as Key and selection as curresponding Value.
Also instead of doing these operations with array of BOOL's , you can update the code as below.
#property (nonatomic, strong) NSMutableDictionary * selectedRowCollection;
- (void)viewDidLoad{
self.selectedRowCollection = [[NSMutableDictionary alloc] init];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
id object = contactsObjects[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedRowCollection setObject:#"1" forKey:[NSString stringWithFormat:#"%d",indexPath.row]];
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedRowCollection removeObjectForKey:[NSString stringWithFormat:#"%d",indexPath.row]];
}
//slow-motion selection animation.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL showCheckmark = [[self.selectedRowCollection valueForKey:[NSString stringWithFormat:#"%d",indexPath.row]] boolValue];
if (showCheckmark == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
Note: Don't forget remove the dictionary items from dictionary while reloading a new tableview dataset.

BOOL values are wrapped with NSNumber, that's why you get 0's:
_stateArray = [NSMutableArray array];
for (int i = 0 ; i != contactsObjects.count ; i++) [_stateArray addObject:#(NO)];
BOOL showCheckmark = [[_stateArray objectAtIndex:indexPath.row] boolValue];
if (showCheckmark == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSLog(#"It hit showCheckmark = YES, and stateArray is %#",[[_stateArray objectAtIndex:indexPath.row] boolValue] ? #"YES" : #"NO");
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(#"It hit showCheckmark = NO, and stateArray is %#",[[_stateArray objectAtIndex:indexPath.row] boolValue] ? #"YES" : #"NO");
}
BOOL is not object, so you cannot use the %# format specifier. You need to handle this manually

Try this,
Update your loop to populate _stateArray by
for (int i = 0 ; i != contactsObjects.count ; i++) {
[_stateArray addObject:[NSNumber numberWithBool:NO]];
}

Related

Adding/removing object to mutable array

I have allSpecialities array, and selectedSpecialities array. I'm downloading those arrays from the server, parse them to object and adding them to those arrays. Now, I want to check/uncheck some specialities. I've tried with containsObject, but that's not working, because those objects are not on the same memory location. This is code that I've done so far, and it's working, but I have problem how to add them to this array.
in cellForRowAtIndexPath:
for (Speciality *specTemp in self.selectedSpecialities) {
if (speciality.specialityId == specTemp.specialityId) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
in didSelect:
Speciality *speciality = [[Speciality alloc]init];
speciality = self.allSpecialities[indexPath.row];
NSMutableArray *tempSelectedSpecialities = [[NSMutableArray alloc]initWithArray:self.selectedSpecialities];
int i=0;
for (Speciality *tempSpeciality in tempSelectedSpecialities) {
if (tempSpeciality.specialityId == speciality.specialityId) {
[self.selectedSpecialities removeObjectAtIndex:i];
}
else {
}
i++;
}
[self.delegate companySpecialities:self.selectedSpecialities];
[self.specialitiesTableView reloadData];
I have declare one Mutable array in .h to store a data
NSMutableArray *selectedMarks;
assign memory in viewDidLoad
selectedMarks = [NSMutableArray new];
add and remove object in didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
TableViewCell *cell = (TableViewCell *)[self.tblview cellForRowAtIndexPath:indexPath];
NSString *strIndex=[NSString stringWithFormat:#"%ld",(long)indexPath.section];
if ([selectedMarks containsObject:strIndex])// Is selected?
{
[selectedMarks removeObject:strIndex];
}
else{
[selectedMarks addObject:strIndex];
}
}
in cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CRTableViewCellIdentifier = #"TableViewCell";
TableViewCell *cell = (TableViewCell *)[self.tblview dequeueReusableCellWithIdentifier:CRTableViewCellIdentifier];
if (cell == nil) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CRTableViewCellIdentifier];
}
cell.backgroundColor=[UIColor colorWithRed:122/255.0 green:196/255.0 blue:251/255.0 alpha:1];
// Check if the cell is currently selected (marked)
NSString *txtQRCodeid = [[[dictListQR objectForKey:#"boxlist"]objectAtIndex:indexPath.section]valueForKey:#"qr_code_id"];
NSString *text1 = [[[dictListQR objectForKey:#"boxlist"]objectAtIndex:indexPath.section]valueForKey:#"box_name"];
NSString *text=[NSString stringWithFormat:#"QR Code %ld with %#",indexPath.section+1,text1];
cell.isSelected = [selectedQR containsObject:txtQRCodeid] ? YES : NO;
if (cell.isSelected) {
[cell.btnSelection setImage:[UIImage imageNamed:#"check"] ];
// set image of selected
}
else{
[cell.btnSelection setImage:[UIImage imageNamed:#"uncheck"] ];
// set unselected image
}
cell.lblQRcodeText.text=text;
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:15];
return cell;
}
It's Work for me

How to store, retrieve check or unchecked cells

I am trying to save the checkmark that i place on a cell and then retrieve it. I have 11 cells in that section.
I tried to use this link as a guide and it works. But i want only need one checkmark to be saved rather than many.
And also i want to set checkmark for all cells by default. How would i achieve this
My Code :
- (NSString *)getKeyForIndex:(int)index{
return [NSString stringWithFormat:#"KEY%d",index];
}
- (BOOL) getCheckedForIndex:(int)index {
if([[[NSUserDefaults standardUserDefaults] valueForKey:[self getKeyForIndex:index]] boolValue]==YES) {
return YES;
}
else
{
return NO;
}
}
- (void) checkedCellAtIndex:(int)index
{
BOOL boolChecked = [self getCheckedForIndex:index];
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:!boolChecked] forKey:[self getKeyForIndex:index]];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if(section == 4) {
if([self getCheckedForIndex:indexPath.row]==YES) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = nil;
NSString *key = [_keys objectAtIndex:indexPath.section];
NSArray *name = [_names objectForKey:key];
static NSString *MyCellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyCellIdentifier];
cell.textLabel.text = [name objectAtIndex:indexPath.row];
if(section == 4) {
[self checkedCellAtIndex:indexPath.row];
if([self getCheckedForIndex:indexPath.row]==YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Solution can be tricky :
Maintain one array same to tableview datasource array.
Say for example u have NSMutableArray *mutArrNames which tableview datasource. Now NSMutableArray *mutArrNamesCheckListwhich shows which one is checked or not;
Intially nothing is selected so add 0 to uncheck one:
for(int i =0; i<[mutArrNames count];i++)
{
[mutArrNamesCheckList addObject:#"0"];
}
Now use like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if(section == 4) {
//check from mutArrNamesCheckList's list if cell is check one or not
if([[mutArrNamesCheckList objectAtIndex:indexPath.row] intValue] == 1) //checked one
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else //unchecked one
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
}
return cell;
}
Here it can be used according to your requirement like allow mutiple selection or single selection.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//get cell object
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(section == 4)
{
if([[mutArrNamesCheckList objectAtIndex:indexPath.row] intValue] == 1) //checked one
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
//replace 0 with 1 as check one
[mutArrNamesCheckList replaceObjectAtIndex:indexPath.row withObject:#"0"];
}
else //unchecked one
{
cell.accessoryType = UITableViewCellAccessoryNone;
//replace 1 with 0 as uncheck one
[mutArrNamesCheckList replaceObjectAtIndex:indexPath.row withObject:#"1"];
}
}
}
For selection and unselection of all cell add this in button's action method. Use this :
//remove all as new objects will be added
[mutArrNamesCheckList removeAllObjects];
if(!btnCheckAll.selected)//selected property used - default is no so all not selected
{
//make all selected
for(int i =0; i<[mutArrNames count];i++)
{
[mutArrNamesCheckList addObject:#"1"];
}
//change buttons image here
}
else
{
//make all unselected
for(int i =0; i<[mutArrNames count];i++)
{
[mutArrNamesCheckList addObject:#"0"];
}
//change buttons image here
}
//tableView reload
[yourtableView reloadData];
btnCheckAll.selected = !btnCheckAll.selected;
Add mutArrNamesCheckList in AppDelegate to be visible in whole Application.
So remove iteration we done on top of above answer in our viewcontroller as we didn't wanted to use gobally
EDIT : added toggling in didSelectRowAtIndexPath + clicked select all button, all cell is checked else unchecked

Retaining UITableViewCell selection statuses

Why the UITableViewCells don't reload the checkmarks after selecting, scrolling away, then scrolling back?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
#define CHECK_NULL_STRING(str) ([str isKindOfClass:[NSNull class]] || !str)?#"":str
static NSString *CellIdentifier = #"inviteCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
cell.textLabel.highlightedTextColor = [UIColor colorWithHexString:#"#669900"];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.backgroundColor = [UIColor blackColor];
cell.textLabel.textColor = [UIColor whiteColor];
[[UITableViewCell appearance] setTintColor:[UIColor colorWithHexString:#"#669900"]];
if (cell == nil) {
cell = [[UITableViewCell alloc] init];
}
if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; }
BOOL isSearching = tableView != self.tableView;
NSArray *arrayToUse = (isSearching ? searchResults : contactsObjects);
id p = arrayToUse[indexPath.row];
NSString *fName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByFirstName));
NSString *lName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByLastName));
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", CHECK_NULL_STRING(fName), CHECK_NULL_STRING(lName)];
BOOL showCheckmark = [[stateArray objectAtIndex:indexPath.row] boolValue];
if (showCheckmark == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSLog(#"It hit showCheckmark = YES, and stateArray is %#",stateArray[indexPath.row]);
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(#"It hit showCheckmark = NO, and stateArray is %#",stateArray[indexPath.row]);
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
id object = contactsObjects[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[stateArray insertObject:[NSNumber numberWithBool:YES] atIndex:indexPath.row];
[selectedObjects addObject:object];
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
[stateArray insertObject:[NSNumber numberWithBool:NO] atIndex:indexPath.row];
[selectedObjects removeObject:object];
}
//slow-motion selection animation.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
You missed out the ! (inverse operator) on the following line meaning that the state will always be the same.
[stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:[[stateArray objectAtIndex:indexPath.row] boolValue]]];
It should be
[stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:![[stateArray objectAtIndex:indexPath.row] boolValue]]];
Edit --- I've refactored both methods because it can be done with a lot less code and it will completely simplify the methods for you.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"inviteCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
BOOL isSearching = tableView != self.tableView;
NSArray *arrayToUse = (isSearching ? searchResults : contactsObjects);
id p = arrayToUse[indexPath.row];
NSString *fName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByFirstName));
NSString *lName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByLastName));
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", CHECK_NULL_STRING(fName), CHECK_NULL_STRING(lName)];
BOOL showCheckmark = [stateArray[indexPath.row] boolValue];
if (showCheckmark == YES) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
id object = contactsObjects[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[selectedObjects addObject:object];
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[selectedObjects removeObject:object];
}
stateArray[indexPath.row] = #(cell.accessoryType == UITableViewCellAccessoryCheckmark);
}
I suggest a more object oriented approach. This will ensure that your code is flexible and displays correctly all the time.
For each item you wish to display in your table, have a corresponding object. You mentioned that you are displaying contacts, so let's suppose your object is called "Contact":
//Contact.h
#interface Contact : NSObject
#property BOOL selected;
#property NSString *name;
#end
//Contact.m
#import Contact.h
#implementation Contact
+ (id) contactWithName:(NSString*)name {
Contact *nContact = [Contact new];
nContact.name = name;
nContact.selected = NO;
return nContact;
}
#end
Then, just make your view work something like this:
//ContactView.m
#interface ContactView()
#property NSMutableArray *contacts;
#end
#implementation ContactView
#synthesize contacts;
- (void) viewDidLoad {
[super viewDidLoad];
//get your contact list here. When creating contacts, be sure to assign their selected and their name as you require.
contacts = #[[Contact contactWithName:#"John"], [Contact contactWithName:#"Jane"]];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = #"inviteCell";
UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
Contact *cellContact = [contacts objectAtIndex:indexPath.row];
cell.textLabel.text = cellContact.name;
cell.accessoryType = cellContact.selected == YES ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Contact *cellContact = [contacts objectAtIndex:indexPath.row];
cellContact.selected = !cellContact.selected;
[contacts replaceObjectAtIndex:indexPath.row withObject:cellContact];
[tableView reloadData]; //to refresh without animation
//[tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [tableView numberOfSections])] withRowAnimation:UITableViewRowAnimationTop]; //to refresh with animation
}
#end
And boom, easy to use tables that always look right, queue properly, and are object oriented for easy maintenance later.
The cell selection problem was not solved, even when insertObject was replaced with replaceWithObject, however, one should not waste time setting BOOL objects with an NSInteger inside an NSMutableArray. Instead, for cell selection memory, one should use NSDictionary like this:
#property (nonatomic, strong) NSMutableDictionary * selectedRowCollection;
- (void)viewDidLoad{
self.selectedRowCollection = [[NSMutableDictionary alloc] init];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
id object = contactsObjects[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedRowCollection setObject:#"1" forKey:[NSString stringWithFormat:#"%d",indexPath.row]];
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedRowCollection removeObjectForKey:[NSString stringWithFormat:#"%d",indexPath.row]];
}
//slow-motion selection animation.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL showCheckmark = [[self.selectedRowCollection valueForKey:[NSString stringWithFormat:#"%d",indexPath.row]] boolValue];
if (showCheckmark == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
You are not doing this UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
Allocating is necessary if cell is nil. Or it cause problem while scrolling.

UITableView select a row per section

I would like to make a selection like this
How can I change my
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
delegate method to work in accordance with my requirement.
Why so complicated? Just deselect all cells of the same section before the user selects a new one.
First allow multiple selection for your UITableView. Then implement this delegate method:
Swift 3 version:
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath?
{
for vcip in tableView.indexPathsForSelectedRows ?? [] {
if vcip.section == indexPath.section && vcip.item != indexPath.item {
tableView.deselectRow(at: vcip, animated: false)
}
}
return indexPath
}
Keep a property in your view controller called selectedRow, which represents the indexPath of tableview that represents the checked item in a table section.
In your view controller's -tableView:cellForRowAtIndexPath: delegate method, set the accessoryType of the cell to UITableViewCellAccessoryCheckmark if the cell's indexPath equals the selectedRow indexpath value. Otherwise, set it to UITableViewCellAccessoryNone.
In your view controller's -tableView:didSelectRowAtIndexPath: delegate method, set the selectedRow value to the indexPath.row that is selected, e.g.: self.selectedRow = indexPath.row
This won't be a good solution.
Use a NSMutableArray for storing the selected sections.
NSMutableArray *selectedSections; //instance variable
selectedSections= [[NSMutableArray alloc] init]; //in viewDidLoad
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *section = [NSNumber numberWithInt:indexPath.section];
if([selectedSections containsObject:section]
return nil;
else
{
[selectedSections addObject:section];
return indexPath;
}
}
When you deselect a row write the below code there:
[selectedSections removeObject:[NSNumber numberWithInt:indexPath.section]];
LimeRed has a great answer elsewhere in this thread, but it is not complete. The key issue is that the OP needs to have the accessory checkmark removed. Simply calling deselectRow will not remove the checkmark. Per the documentation, deselectRow does not call the delegate method tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) where the removal of the checkmark code might be located. Therefore you need handle this removal as part of the code that LimeRed wrote.
Here is a more complete implementation that removes the accessory checkmark again based on LimeRed's solution:
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath?
{
for path in tableView.indexPathsForSelectedRows ?? []
{
if path.section == indexPath.section && path.item != indexPath.item
{
let cell = tableView.cellForRow(at: path)
cell?.accessoryType = UITableViewCellAccessoryType.none
tableView.deselectRow(at: path, animated: false)
}
}
return indexPath
}
try like this,
In .h
#property (nonatomic, retain) NSIndexPath *checkedIndexPath;
In .m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section==0)
{
// to check and Uncheck the row
if(self.checkedIndexPath)
{
UITableViewCell* uncheckCell = [tableView1
cellForRowAtIndexPath:self.checkedIndexPath];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
if([self.checkedIndexPath isEqual:indexPath])
{
self.checkedIndexPath = nil;
}
else
{
UITableViewCell* cell = [tableView1 cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.checkedIndexPath = indexPath;
}
}
}
This one's gonna be ViewController.h
#interface ViewController : UITableViewController
{
NSMutableArray *list;
NSMutableArray *sectionList;
NSIndexPath *oldIndexPath0;
int row0;
NSIndexPath *oldIndexPath1;
int row1;
NSIndexPath *oldIndexPath2;
int row2;
NSIndexPath *oldIndexPath3;
int row3;
NSString *othersString;
NSString *timeString;
NSString *pRoomString;
NSString *parkingString;
NSString *smokingString;
NSString *select0;
NSString *select1;
NSString *select2;
NSString *select3;
}
#end
This one's ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewWillAppear:(BOOL)animated
{
// initial row by 100;
row0 = 100;
row1 = 100;
row2 = 100;
row3 = 100;
// initial strings by #”"
othersString = [NSString stringWithFormat:#""];
timeString = [NSString stringWithFormat:#""];
pRoomString = [NSString stringWithFormat:#""];
parkingString = [NSString stringWithFormat:#""];
smokingString = [NSString stringWithFormat:#""];
select0 = #"";
select1 = #"";
select2 = #"";
select3 = #"";
// Get row index
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:#"tmp/rowString.txt"];
NSData *rowData = [fileManager contentsAtPath:fileName];
// From NSData to NSString
NSString *rowString = [[NSString alloc] initWithData:rowData encoding:NSUTF8StringEncoding];
if (rowString) {
// spit row string
NSArray *rowArray = [rowString componentsSeparatedByString:#":"];
for (int i=0; i<[rowArray count]; i++) {
NSString *indexVal = [rowArray objectAtIndex:i];
if ([indexVal length] != 0) {
// set row value
if (i == 0) {
NSString *row0Str = [rowArray objectAtIndex:0];
row0 = [row0Str intValue];
}
if (i == 1) {
NSString *row1Str = [rowArray objectAtIndex:1];
row1 = [row1Str intValue];
}
if (i == 2) {
NSString *row2Str = [rowArray objectAtIndex:2];
row2 = [row2Str intValue];
}
if (i == 3) {
NSString *row3Str = [rowArray objectAtIndex:3];
row3 = [row3Str intValue];
}
}
}
}
// Update the view with current data before it is displayed.
[super viewWillAppear:animated];
//Initialize the array.
list = [[NSMutableArray alloc] initWithCapacity:0];
sectionList = [[NSMutableArray alloc] initWithCapacity:0];
// section header
NSArray *sectionHeaderArray = [NSArray arrayWithObjects:#"01",#"02",#"03",#"04", nil];
NSDictionary *sectionHeaderDic = [NSDictionary dictionaryWithObject:sectionHeaderArray forKey:#"section"];
[sectionList addObject:sectionHeaderDic];
// time list
NSArray *timeArray = [NSArray arrayWithObjects:#"time 01",#"time 01",#"time 01", nil];
NSDictionary *timeDic = [NSDictionary dictionaryWithObject:timeArray forKey:#"time"];
// private room
NSArray *pRoomArray = [NSArray arrayWithObjects:#"room 01",#"room 02", nil];
NSDictionary *pRoomDic = [NSDictionary dictionaryWithObject:pRoomArray forKey:#"pRoom"];
// parking
NSArray *parkingArray = [NSArray arrayWithObjects:#"park 01",#"park 02",#"park 03", nil];
NSDictionary *parkingDic = [NSDictionary dictionaryWithObject:parkingArray forKey:#"parking"];
// smoking
NSArray *smokingArray = [NSArray arrayWithObjects:#"smoke 01",#"smoke 02",#"smoke 03", nil];
NSDictionary *smokingDic = [NSDictionary dictionaryWithObject:smokingArray forKey:#"smoking"];
// add all dictionary to list
[list addObject:timeDic];
[list addObject:pRoomDic];
[list addObject:parkingDic];
[list addObject:smokingDic];
// Scroll the table view to the top before it appears
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//Number of section
return [list count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//Get the dictionary object
NSDictionary *dictionary = [list objectAtIndex:section];
NSArray *array;
switch (section) {
case 0:
// time array
array = [dictionary objectForKey:#"time"];
break;
case 1:
// pRoom array
array = [dictionary objectForKey:#"pRoom"];
break;
case 2:
// parking array
array = [dictionary objectForKey:#"parking"];
break;
case 3:
// smoking array
array = [dictionary objectForKey:#"smoking"];
break;
default:
break;
}
//Number of rows
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Budget";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
UITableViewCellStyleSubtitle;
}
//Get the dictionary object
NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
NSArray *array;
switch (indexPath.section) {
case 0:
// time array
array = [dictionary objectForKey:#"time"];
if (indexPath.row == row0 ) {
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
break;
case 1:
// pRoom array
array = [dictionary objectForKey:#"pRoom"];
if (indexPath.row == row1) {
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
break;
case 2:
// parking array
array = [dictionary objectForKey:#"parking"];
if (indexPath.row == row2) {
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
break;
case 3:
// smoking array
array = [dictionary objectForKey:#"smoking"];
if (indexPath.row == row3) {
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
break;
default:
break;
}
cell.textLabel.text = [array objectAtIndex:indexPath.row];
NSLog(#"index cell");
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *title = nil;
//Get the dictionary object
NSDictionary *dictionary = [sectionList objectAtIndex:0];
NSArray *array = [dictionary objectForKey:#"section"];
title = [array objectAtIndex:section];
return title;
}
#pragma mark -
#pragma mark Table view selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
switch(indexPath.section)
{
case 0:
{
UITableViewCell *cell1 = [tableView cellForRowAtIndexPath:indexPath];
if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark) {
cell1.accessoryType = UITableViewCellAccessoryNone;
row0 = 100;
timeString = #"";
}else {
NSIndexPath *SIndexPath0 = [NSIndexPath indexPathForRow:row0 inSection:0];
if ([[tableView cellForRowAtIndexPath:SIndexPath0 ] accessoryType] == UITableViewCellAccessoryCheckmark) {
[[tableView cellForRowAtIndexPath:SIndexPath0] setAccessoryType:UITableViewCellAccessoryNone];
}
if (oldIndexPath0 == nil) {
oldIndexPath0 = indexPath;
}
UITableViewCell *cell2 = nil;
if (oldIndexPath0 != indexPath) {
cell2 = [tableView cellForRowAtIndexPath:oldIndexPath0];
}
cell1.accessoryType = UITableViewCellAccessoryCheckmark;
if (cell2) {
cell2.accessoryType = UITableViewCellAccessoryNone;
}
//Get the dictionary object
NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"time"];
timeString = [array objectAtIndex:indexPath.row];
row0 = indexPath.row;
oldIndexPath0 = nil;
}
select0 = #"marked";
break;
}
case 1:
{
UITableViewCell *cell1 = [tableView cellForRowAtIndexPath:indexPath];
if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark) {
cell1.accessoryType = UITableViewCellAccessoryNone;
row1 = 100;
pRoomString = #"";
}else {
NSIndexPath *SIndexPath1 = [NSIndexPath indexPathForRow:row1 inSection:1];
if ([[tableView cellForRowAtIndexPath:SIndexPath1 ] accessoryType] == UITableViewCellAccessoryCheckmark) {
[[tableView cellForRowAtIndexPath:SIndexPath1] setAccessoryType:UITableViewCellAccessoryNone];
}
if (oldIndexPath1 == nil) {
oldIndexPath1 = indexPath;
}
UITableViewCell *cell2 = nil;
if (oldIndexPath1 != indexPath) {
cell2 = [tableView cellForRowAtIndexPath:oldIndexPath1];
}
cell1.accessoryType = UITableViewCellAccessoryCheckmark;
if (cell2) {
cell2.accessoryType = UITableViewCellAccessoryNone;
}
//Get the dictionary object
NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"pRoom"];
pRoomString = [array objectAtIndex:indexPath.row];
row1 = indexPath.row;
oldIndexPath1 = nil;
}
select1 = #"marked";
break;
}
case 2:
{
UITableViewCell *cell1 = [tableView cellForRowAtIndexPath:indexPath];
if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark) {
cell1.accessoryType = UITableViewCellAccessoryNone;
row2 = 100;
parkingString = #"";
}else {
NSIndexPath *SIndexPath2 = [NSIndexPath indexPathForRow:row2 inSection:2];
if ([[tableView cellForRowAtIndexPath:SIndexPath2 ] accessoryType] == UITableViewCellAccessoryCheckmark) {
[[tableView cellForRowAtIndexPath:SIndexPath2] setAccessoryType:UITableViewCellAccessoryNone];
}
if (oldIndexPath2 == nil) {
oldIndexPath2 = indexPath;
}
UITableViewCell *cell2 = nil;
if (oldIndexPath2 != indexPath) {
cell2 = [tableView cellForRowAtIndexPath:oldIndexPath2];
}
cell1.accessoryType = UITableViewCellAccessoryCheckmark;
if (cell2) {
cell2.accessoryType = UITableViewCellAccessoryNone;
}
//Get the dictionary object
NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"parking"];
parkingString = [array objectAtIndex:indexPath.row];
row2 = indexPath.row;
oldIndexPath2 = nil;
}
select2 = #"marked";
break;
}
case 3:
{
UITableViewCell *cell1 = [tableView cellForRowAtIndexPath:indexPath];
if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark) {
cell1.accessoryType = UITableViewCellAccessoryNone;
row3 = 100;
smokingString = #"";
}else {
NSIndexPath *SIndexPath3 = [NSIndexPath indexPathForRow:row3 inSection:3];
if ([[tableView cellForRowAtIndexPath:SIndexPath3 ] accessoryType] == UITableViewCellAccessoryCheckmark) {
[[tableView cellForRowAtIndexPath:SIndexPath3] setAccessoryType:UITableViewCellAccessoryNone];
}
if (oldIndexPath3 == nil) {
oldIndexPath3 = indexPath;
}
UITableViewCell *cell2 = nil;
if (oldIndexPath3 != indexPath) {
cell2 = [tableView cellForRowAtIndexPath:oldIndexPath3];
}
cell1.accessoryType = UITableViewCellAccessoryCheckmark;
if (cell2) {
cell2.accessoryType = UITableViewCellAccessoryNone;
}
//Get the dictionary object
NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"smoking"];
smokingString = [array objectAtIndex:indexPath.row];
row3 = indexPath.row;
oldIndexPath3 = nil;
}
select3 = #"marked";
break;
}
default:
break;
}
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
// Cancle button and add an event handler
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Cancle"
style:UIBarButtonSystemItemCancel
target:self
action:#selector(handleCancle:)];
// Cancle button and add an event handler
self.navigationItem.rightBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Use"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(handleUse:)];
}
- (void) handleCancle:(id)sender
{
// pop the controller
[self.navigationController popViewControllerAnimated:YES];
}
- (void) handleUse:(id)sender{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *fileName;
// Get row index value
fileName = [NSHomeDirectory() stringByAppendingPathComponent:#"tmp/othersString.txt"];
NSData *rowValData = [fileManager contentsAtPath:fileName];
// From NSData to NSString
NSString *rowValString = [[NSString alloc] initWithData:rowValData encoding:NSUTF8StringEncoding];
NSString *oldTimeString = #"";
NSString *oldpRoomString = #"";
NSString *oldParkingString = #"";
NSString *oldSmokingString = #"";
if (rowValString) {
// spit row string
NSArray *rowValArray = [rowValString componentsSeparatedByString:#":"];
for (int i=0; i<[rowValArray count]; i++) {
if ([rowValArray objectAtIndex:i] != #"") {
// set row value
if (i == 0 ) {
oldTimeString = [rowValArray objectAtIndex:0];
}
if (i == 1 ) {
oldpRoomString = [rowValArray objectAtIndex:1];
}
if (i == 2 ) {
oldParkingString = [rowValArray objectAtIndex:2];
}
if (i == 3) {
oldSmokingString = [rowValArray objectAtIndex:3];
}
}
}
}
if (select0 == #"") {
timeString = oldTimeString;
}
if (select1 == #"") {
pRoomString = oldpRoomString;
}
if (select2 == #"") {
parkingString = oldParkingString;
}
if (select3 == #"") {
smokingString = oldSmokingString;
}
// make othersString string
othersString = [NSString stringWithFormat:#"%#:%#:%#:%#", timeString, pRoomString, parkingString, smokingString];
// write othersString to othersString.txt file
fileName= [NSHomeDirectory() stringByAppendingPathComponent:#"tmp/othersString.txt"];
NSData *othersData = [othersString dataUsingEncoding:NSUTF8StringEncoding];
[fileManager createFileAtPath:fileName contents:othersData attributes:nil];
// make row data in string
NSString *rowString = [NSString stringWithFormat:#"%i:%i:%i:%i", row0,row1,row2,row3];
// write othersString to othersString.txt file
fileName = [NSHomeDirectory() stringByAppendingPathComponent:#"tmp/rowString.txt"];
NSData *rowData = [rowString dataUsingEncoding:NSUTF8StringEncoding];
[fileManager createFileAtPath:fileName contents:rowData attributes:nil];
// pop the controller
[self.navigationController popViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
[list release];
}
#end
Got this stuff from this post, as this was in Japanese I changed it. Thanks to the author.
After a lot of modifications I have arrived with this
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [aTableView cellForRowAtIndexPath:indexPath];
if(indexPath.section == 0)
{
if([section1Rows count] == 0)
{
[section1Rows addObject:[NSNumber numberWithInt:indexPath.row]];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
[section1Rows removeObjectAtIndex:0];
for (UITableViewCell *cell in [tabview visibleCells]) {
cell.accessoryType = UITableViewCellAccessoryNone;
}
[section1Rows addObject:[NSNumber numberWithInt:indexPath.row]];
NSLog(#"%#",section1Rows);
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
if(indexPath.section == 1)
{
if([section2Rows count] == 0)
{
[section2Rows addObject:[NSNumber numberWithInt:indexPath.row]];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
[section2Rows removeObjectAtIndex:0];
for (UITableViewCell *cell in [tabview visibleCells]) {
cell.accessoryType = UITableViewCellAccessoryNone;
}
[section2Rows addObject:[NSNumber numberWithInt:indexPath.row]];
NSLog(#"%#",section2Rows);
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
if(indexPath.section == 2)
{
if([section3Rows count] == 0)
{
[section3Rows addObject:[NSNumber numberWithInt:indexPath.row]];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
[section3Rows removeObjectAtIndex:0];
for (UITableViewCell *cell in [tabview visibleCells]) {
cell.accessoryType = UITableViewCellAccessoryNone;
}
[section3Rows addObject:[NSNumber numberWithInt:indexPath.row]];
NSLog(#"%#",section3Rows);
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
}
I'll explain the problem in steps,
I have selected a row in 3 sections, If I select a row again in any of the sections... then everything goes haywire. How can I deselect the previously selected row and highlight the then selected row?
Thanks.

iOS: How to save only one checkmark (for UITableView) in NSUserDefaults?

i have a question regarding NSUserDefaults. I am trying to save the checkmark that i place on a cell and then retrieve it when the app crashes or when user closes app and so on. I tried to use this post post as a guide, but no luck, but here's what i have so far. The code from the post works, however, i only need one checkmark to be saved rather than many. How would i achieve this?
#implementation ClientsViewController
#synthesize clientsInt; // This is just a variable that helps me do the drill down part of the rootviewcontroller
#synthesize checkedIndexPath;
- (NSString *)getKeyForIndex:(int)index
{
return [NSString stringWithFormat:#"KEY%d",index];
}
- (BOOL) getCheckedForIndex:(int)index
{
if([[[NSUserDefaults standardUserDefaults] valueForKey:[self getKeyForIndex:index]] boolValue]==YES)
{
return YES;
}
else
{
return NO;
}
}
- (void) checkedCellAtIndex:(int)index
{
BOOL boolChecked = [self getCheckedForIndex:index];
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:!boolChecked] forKey:[self getKeyForIndex:index]];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if([self getCheckedForIndex:indexPath.row]==YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
// Configure the cell...
if (clientsInt == 0) {
cell.textLabel.text = [array1 objectAtIndex:indexPath.row];
}
else if (clientsInt == 1) {
cell.textLabel.text = [array2 objectAtIndex:indexPath.row];
}
else if (clientsInt == 2) {
cell.textLabel.text = [array3 objectAtIndex:indexPath.row];
}
else if (clientsInt == 3) {
cell.textLabel.text = [array4 objectAtIndex:indexPath.row];
}
if([self.checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Uncheck the previous checked row
if(self.checkedIndexPath)
{
UITableViewCell* uncheckCell = [tableView cellForRowAtIndexPath:self.checkedIndexPath];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.checkedIndexPath = indexPath;
[self checkedCellAtIndex:indexPath.row];
if([self getCheckedForIndex:indexPath.row]==YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Maybe try something like this every time the user checks a row:
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:index] forKey:#"kCheckedBoxKey"];
Since each time, you would save the index under the same key (#"kCheckedBoxKey"), only one index will ever be stored, and it will always be the latest one that the user checked. All you would need to do the next time you load is ask userDefaults if it can find a value for the key #"kCheckedBoxKey", and if so, you would respond by programatically checking the index that was stored.
(you'd of course also want to clean it up by using #define CHECKED_KEY #"kCheckedBoxKey" at the top of the file, and use CHECKED_KEY instead of the literal string to protect against misspellings. At any rate, the point is to make sure you always save & restore using that same key.)
I recently had to save the state of each cell in my table view when the user selected or deselected them to add or remove checkmarks. Here is the snippet of code I used to save to a .plist file (let me know if you need the whole implementation I came up with:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *contentForThisRow = [[self list] objectAtIndex:[indexPath row]];
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d%d", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *documentDirectory = [(AppDelegate *)[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory];
NSString *PlistPath = [documentDirectory stringByAppendingPathComponent:#"Settings.plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:PlistPath];
NSString *row = [NSString stringWithFormat:#"%d",indexPath.row];
if([[dict objectForKey:row]isEqualToString:#"0"])
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
[[cell textLabel] setText:contentForThisRow];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *documentDirectory = [(AppDelegate *)[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory];
NSString *PlistPath = [documentDirectory stringByAppendingPathComponent:#"Settings.plist"];
NSMutableDictionary *plist = [NSMutableDictionary dictionaryWithContentsOfFile:PlistPath];
UITableViewCell *cell = [self._tableView cellForRowAtIndexPath:indexPath];
NSString *row = [NSString stringWithFormat:#"%d",indexPath.row];
if(cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSString *on = #"1";
[plist setObject:on forKey:row];
[plist writeToFile:PlistPath atomically:YES];
}
else if(cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSString *off = #"0";
[plist setObject:off forKey:row];
[plist writeToFile:PlistPath atomically:YES];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
You only need to save the index of the selected row

Resources