2

I'm new to ios development, and I'm using checkmark for cells in a UITableView.

I want storing checked cell in a NSUserDefaults database, When I reload the app, the checked cell that previously selected will be display, I'm try to defferent ways, but still failed to implement it.

Anybody can help me? I would be highly appreciate it. Sorry, my english is not good.

My code is below:

#import "FirstRowSubview.h"

@interface FirstRowSubview ()

@end

@implementation FirstRowSubview

@synthesize array = _array;
@synthesize lastIndexPath = _lastIndexPath;


- (void)viewDidLoad
{
    [super viewDidLoad];
    NSMutableArray *list = [[NSMutableArray alloc] initWithObjects:@"ffgfgh", @"564654", @"56548", @"fgmjfgmf", @"ggkdj", nil];
    self.array = list;
    [list release];

}

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.array = nil;
}


#pragma mark -
#pragma mark - TableView Datasource Methods

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_array count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *subviewCells = @"Cells";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:subviewCells];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:subviewCells];
    }
    NSUInteger oldRow = [_lastIndexPath row];
    cell.accessoryType = (indexPath.row == oldRow && _lastIndexPath != nil) ?
    UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
    cell.textLabel.text = [_array objectAtIndex:indexPath.row];

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[NSNumber numberWithInt:_lastIndexPath.row] forKey:@"lastIndexPath"];
    [defaults synchronize];



    return cell;
 }

#pragma mark -
#pragma mark - TableView Delegate Methods

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    int newRow = [indexPath row];
    int oldRow = (_lastIndexPath != nil) ? [_lastIndexPath row] : -1;

    if (newRow != oldRow) {
        UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
        newCell.accessoryType = UITableViewCellAccessoryCheckmark;

        UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:_lastIndexPath];
        oldCell.accessoryType = UITableViewCellAccessoryNone;

        [indexPath retain];
        [_lastIndexPath release];
        _lastIndexPath = indexPath;


        [tableView deselectRowAtIndexPath:indexPath animated:YES];


    }

}
The iOSDev
  • 5,237
  • 7
  • 41
  • 78
Andy_24
  • 1,353
  • 2
  • 12
  • 20

3 Answers3

10

It can be easy to store and retrieve checked cell(s) information with NSUserDefaults.

NSUserDefaults can store the data interms of Key / Value pair. Here in your case value could be boolean and key could combination of NSString & indexpath.row from UITableView.

You can make a functions like,

- (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];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_array count];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //Here, you can check for previously checked cells like

    static NSString *subviewCells = @"Cells";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:subviewCells];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:subviewCells];
    }

    cell.textLabel.text = [_array objectAtIndex:indexPath.row];

    if([self getCheckedForIndex:indexPath.row]==YES)
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    //Use checkedCellAtIndex for check or uncheck cell
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    [self checkedCellAtIndex:indexPath.row];

    if([self getCheckedForIndex:indexPath.row]==YES)
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
}

P.S. Please, note that, this method will only useful and suggested if order of data from your NSArray will always in same order. Other then NSUserDefaults you've options like SQLite Database or plist file or any other option! Thanks :)

Hemang
  • 26,840
  • 19
  • 119
  • 186
  • Firstly, big thanks for your reply! But feel sorry i'm still very confused, Which parts of my code should modified? or just add your code above? Is the function for above code only just used to store and retrieve checked cell(s)? – Andy_24 Aug 25 '12 at 10:40
  • @Andy_24, glad to help! Yes, you only have to add above code into your code! That's all. That would help you to, store, retrieve check or unchecked cells. – Hemang Aug 25 '12 at 11:23
  • Great, it's works normal! But weird that checkmark duplicated into other cells, my tableView only allows selected one item for checkmark, i wonder what reason causes this problem? – Andy_24 Aug 25 '12 at 13:52
  • @Andy_24, This code works to select or unselect multiple items at the same time! I'll check for it soon! – Hemang Aug 27 '12 at 07:57
  • @Andy_24, I've edited code, review it! It'll work for multiple selection. You can make some logic for single selection. – Hemang Aug 27 '12 at 10:22
  • @Hemang Can you please please provide us with implementation for single selection :) – Eshwar Chaitanya May 14 '13 at 05:50
  • @EshwarChaitanya, [**this**](http://stackoverflow.com/questions/10192908/uitableview-checkmark-only-one-row-at-a-time) link can be helpful to you! Good luck! – Hemang May 14 '13 at 05:52
  • Extremely sorry,I have already gone through those links,I am still facing the multiple cell check marks issue,I have even mentioned tableView.allowsMultipleSelection = NO; – Eshwar Chaitanya May 14 '13 at 06:12
3

This is a basic example of how to create an array of NSIndexPaths based on the current selection of the table and then saving that array into NSUserDefaults.

 -(void)viewDidLoad
{
    [super viewDidLoad];
    for (NSIndexPath *indexPath in [[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:@"mySavedMutableArray"]) {
        [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
    }
}

Here you can add objects to the array as they are selected

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [[[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:@"mySavedMutableArray"] addObject:indexPath];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

Here you'll remove the deselected object from the array.

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [[[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:@"mySavedMutableArray"] removeObject:indexPath];
    [[NSUserDefaults standardUserDefaults] synchronize];
}
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
0

The simplest way to get your code working is just put one line in view did load method as follow:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults valueForKey:@"lastIndexPath"])
_lastIndexPath = [defaults valueForKey:@"lastIndexPath"];

This will solve your problem :)

Happy Coding :)

The iOSDev
  • 5,237
  • 7
  • 41
  • 78