Varun Iyer
Varun Iyer

Reputation: 533

Save accessory checkmarks on uitableview when users loads view multiple times

So I've implemented a UIViewController with a tableview, and basically it loads as a set of "filters" for my uicollectionview.

Now, when I click on the checkmarks in my tableview, it "filters" my cells accordingly, but now when I reload the view again I want to display the most recent "checkmarks" I've used, or "filters."

I have seen this being implemented with NSUserDefaults, but I have not been able to successfully implement this.

If anyone could help me, that will be greatly appreciated.

CODE

FiltersViewController.m:

#import "FiltersViewController.h"

@interface FiltersViewController ()

@property (nonatomic, strong) NSMutableSet *selectedRowObjects;
//@property (nonatomic, strong) NSArray *filters;

@end

@implementation FiltersViewController


- (void)viewDidLoad
{
    [super viewDidLoad];

    self.selectedRowObjects = [NSMutableSet setWithCapacity:10];
}

- (IBAction)filtersSelected:(id)sender {
    [self.delegate filtersSelected:self.selectedRowObjects];
}

- (IBAction)cancelFilterSelection:(id)sender {
    [self.delegate filterSelectionCancelled];
}

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


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 10;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"filter" forIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%u", indexPath.row];



    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {


    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    NSString *obj = cell.textLabel.text;

    if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;
        [self.selectedRowObjects removeObject:obj];
    }
    else {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        [self.selectedRowObjects addObject:obj];
    }

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

}
@end

Upvotes: 6

Views: 1644

Answers (7)

Bhavesh Lathigara
Bhavesh Lathigara

Reputation: 1415

you need to check in cellForRowAtIndexPath also. Write this code in this

if([[NSUserDefaults standardUserDefaults] objectForKey:[self getKeyForIndex:indexPath.row]])
{
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
    cell.accessoryType = UITableViewCellAccessoryNone;
}

And yes don't forget to call this method in didSelectRowAtIndexPath

[self checkedCellAtIndex:indexPath.row];

Enjoy.

Upvotes: 5

Amr Mohamed
Amr Mohamed

Reputation: 2380

The best way to save tableView CheckMark with NSUserDefaults

    @interface TableViewController (){
    NSArray *TableTitles;
    NSMutableArray *SelectedRows;
}

viewDidLoad

   - (void)viewDidLoad
{
    [super viewDidLoad];

    // table view array
    TableTitles = [NSArray arrayWithObjects:@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10", nil];

    NSUserDefaults *userDef = [NSUserDefaults standardUserDefaults];
    SelectedRows = [NSMutableArray arrayWithArray:[userDef objectForKey:@"SelectedRows"]];
}

cellForRowAtIndexPath

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    cell.textLabel.text = TableTitles[indexPath.row];

    NSNumber *obj = [NSNumber numberWithInteger:indexPath.row];
    if ([SelectedRows containsObject:obj])
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    return cell;
}

didSelectRowAtIndexPath

 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSNumber *obj = [NSNumber numberWithInteger:indexPath.row];
    if ([SelectedRows containsObject:obj])
    {
        [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
        [SelectedRows removeObject:obj];
        [tableView reloadData];
    }else{
        [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
        [SelectedRows addObject:obj];
        [tableView reloadData];
    }

    NSUserDefaults *userDef = [NSUserDefaults standardUserDefaults];
    [userDef setObject:SelectedRows forKey:@"SelectedRows"];
    [userDef synchronize];
}

updated ...

i updated all code with a new way , it's the best way to save TableView CheckMarks and it's now easy and efficient, now only one array is used for saving and loading , code reduced too much :)

Upvotes: 1

bdparrish
bdparrish

Reputation: 2764

I think what you are looking for is to get the current state of the table for the filters when you enter and exit the view. You need to utilize the - (void)viewWillDisappear:(BOOL)animated to save the current state of the table to your NSUserDefaults, and then use - (void)viewDidLoad and - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to set the checkmark when the table reloads.

@interface FiltersViewController () {
    NSMutableArray *_filterStates;
}

@end

- (void)viewDidLoad {
    filterStates = [[NSMutableArray alloc] init];

    // get state of your current filters in NSUserDefaults, these should be stored as [NSNumber numberWithBool:]
}

- (void)viewWillDisappear:(BOOL)animated {
    // store all of your filters into your NSUserDefaults as [NSNumber numberWithBool:]
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // get your cell from the table

    BOOL isChecked = [[_filterStates objectAtIndex:indexPath.row] boolValue];

    // set the checkmark based on the current state for this filter
}

Upvotes: 0

Ajay Singh Thakur
Ajay Singh Thakur

Reputation: 485

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {

NSString *simpleTableIdentifier = @"cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = ArrayOfObject[indexPath.row];
NSUserDefaults *ud =[NSUserDefaults standardUserDefaults];
if([[ud objectForKey:@"selectedObjectKey "]isEqualToString:ArrayOfObject[indexPath.row]])
{
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
    cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;


}

Upvotes: 2

simalone
simalone

Reputation: 2768

You should load data in NSUserDefaults while call cellForRowAtIndexPath

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"filter" forIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%u", indexPath.row];

    //You should set accessoryType here by NSUserDefaults data
    if ([self getCheckedForIndex:indexPath.row]) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else{
        cell.accessoryType = UITableViewCellAccessoryNone;
    }


    return cell;
}

Upvotes: 0

Surjeet Singh
Surjeet Singh

Reputation: 11939

You have implemented perfectly. You just need to modify you cellForRowAtIndexPath Method

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"filter" forIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%u", indexPath.row];

BOOL checked = [self getCheckedForIndex:indexPath.row];
   if(checked)
       cell.accessoryType = UITableViewCellAccessoryCheckmark;
   else
       cell.accessoryType = UITableViewCellAccessoryNone;


    return cell;
}

Also Call [self checkedCellAtIndex:indexPath.row]; from didSelectRowAtIndexPath method of UITableView.

Upvotes: 1

Jordan
Jordan

Reputation: 3022

You did almost everything right. You just need to put your logic for reading the NSUserDefault values (for the checked boxes) in the cellForRowAtIndexPath delegate method. That is the method that draws the UITableViewCells when they are displayed on screen. Something like this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"filter" forIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%u", indexPath.row];

    if ([self getCheckedForIndex:indexPath.row])
    {
        //code to set checkbox
    }

    return cell;
}

Upvotes: 4

Related Questions