Search code examples
objective-cuitableviewsavensuserdefaultscheckmark

Save checkmark in NSUserDefaults - dynamic TableView


Solution!!

Thanks Josh for all the patience :D

So the code in the initial question always ticks the selected cell and deselects a previously selected cell without saving anything to the NSUserDefaults. After a lot of help from Josh the new code (right below) is the following (exactly the same as in his reply/I only clened it up a little and removed @properties defined in previous attempts to make it work).

The user taps one of the 7 cells. The indexPath of tapped cell is then saved in the NSUserdefaultsand when the TableView is open again a checkmark is displayed next to the previously tapped cell. The indexpath is always saved in the same NSObjectso only one checkmark will ever be displayed.

#import "CycleTableViewController.h"
#import "SettingsTableViewController.h"

@interface CycleTableViewController ()
@property (nonatomic) int selectedRow;
@end

@implementation CycleTableViewController
@synthesize array;

- (void)viewDidLoad {
    //load array containing options
    array=@[@"1", @"2",  @"3", @"4", @"5", @"6", @"7"];

    [super viewDidLoad];
    }

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

- (void) viewWillDisappear:(BOOL)animated{
    //save indexpath of tapped cell to NSUserdefaults
    [[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"cycle"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    }

#pragma mark - Table view data source

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

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

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

    cell.textLabel.text = [array objectAtIndex:indexPath.row];
   
    //display checkmark next to the tapped cell
    if(indexPath.row == self.selectedRow){
       cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    else{
       ell.accessoryType = UITableViewCellAccessoryNone;
        }         
        return cell;
    }

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //assign indexpath to selectedRow, so NSUserdefaults can save them
    self.selectedRow = indexPath.row;        
    [self.tableView reloadData];
    }

    //save indexpath of tapped cell to NSUserdefaults
    [[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"cycle"];
    [[NSUserDefaults standardUserDefaults] synchronize];

@end


Initial question

I've been reading through tons of posts on here on saving an index path to the user defaults, but none of them has worked for me...

In the following TableView I have an array of data (1-7) that is displayed and then passed to another ViewController once a cell is pressed. The pressed cell gets a checkmark and if I go back using the Navigation Controller I can see the checkmark. Only one item is selected at a time. If I press another row, the checkmark changes.

So now I want to save the indexpath of the selected row to the UserDefaults (in the didselectrowat indexpath) and the load it in the viewdidload but I always get a build failed, whatever I try...

Can somebody please point me in the right direction? This should be easy, but I somehow just can't get it to work :/

Updated Code! Once I get it working I'll upload the finished answer!

#import "CycleTableViewController.h"
#import "SettingsTableViewController.h"


@interface CycleTableViewController (){
    NSString *currentCategory; // pointer to the currently checked item
}
// other @property declarations here or in your .m file
#define CHECKED_KEY @"kCheckedBoxKey"

@property (nonatomic) int selectedRow;



@end

@implementation CycleTableViewController
@synthesize array;



- (void)viewDidLoad {
    
    //load tickmark according to newCell;
    
    array=@[@"21+7", @"22+6",  @"23+5", @"24+4", @"25+3", @"26+2", @"28"];

    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
-(void) viewWillAppear:(BOOL)animated {
    self.selectedRow = [[[NSUserDefaults standardUserDefaults] objectForKey:@"cycle"] intValue];
    
 }

#pragma mark - Table view data source

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

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIndentifier=@"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIndentifier forIndexPath:indexPath];
    
    cell.textLabel.text = [array objectAtIndex:indexPath.row];
    
    return cell;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    [[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"cycle"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    NSIndexPath *IndexPath = [NSIndexPath indexPathForRow:self.selectedRow inSection:0];
    UITableViewCell *Cell = [tableView cellForRowAtIndexPath:IndexPath];
    Cell.accessoryType = UITableViewCellAccessoryCheckmark;
    
}

@end


Solution

  • #import "CycleTableViewController.h"
    #import "SettingsTableViewController.h"
    
    
    @interface CycleTableViewController (){
        NSString *currentCategory; // pointer to the currently checked item
    }
    // other @property declarations here or in your .m file
    #define CHECKED_KEY @"kCheckedBoxKey"
    
    @property (nonatomic) int selectedRow;
    
    @end
    
    @implementation CycleTableViewController
    @synthesize array;
    
    - (void)viewDidLoad {
    
        //load tickmark according to newCell;
    
        array=@[@"21+7", @"22+6",  @"23+5", @"24+4", @"25+3", @"26+2", @"28"];
    
        [super viewDidLoad];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (void) viewWillAppear:(BOOL)animated {
        self.selectedRow = [[[NSUserDefaults standardUserDefaults] objectForKey:@"cycle"] intValue];        
     }
    
    - (void) viewWillDisappear:(BOOL)animated{
        [[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"cycle"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return [array count];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIndentifier=@"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIndentifier forIndexPath:indexPath];
    
        cell.textLabel.text = [array objectAtIndex:indexPath.row];
    
        if(indexPath.row == self.selectedRow){
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
         }
        else{
            cell.accessoryType = UITableViewCellAccessoryNone;
        }         
        return cell;
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
         self.selectedRow = indexPath.row;        
         [self.tableView reloadData];
    }
    
    @end