Lion789
Lion789

Reputation: 4482

Not sure why NSUserdefaults is not saving the results?

I am trying to save checked and remove unchecked tablecells into NSUserdefaults but it seems to ignore it as the NSLog in the for loop never gets called not sure why, is there something wrong with this code? (Everything shows up right and the cells get checked and un-checked correctly)

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //setting up nsUser
    userDefaults = [NSUserDefaults standardUserDefaults];

    //current row text
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    NSString *cellName = cell.textLabel.text;

    // Check if current row is selected
    Boolean isNowChecked = NO;
    if([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark)
    {
        isNowChecked = YES;
    }

    if(isNowChecked)
    {
        NSLog(@"UNCHECKING");
        [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;

        //takes away highlight from selection
        [tableView deselectRowAtIndexPath:indexPath animated:YES];

        //retrieve from nsdefaults
        NSMutableArray *arrayOfCategories = [userDefaults objectForKey:@"categories"];

        NSMutableArray *categoriesSelected;

        //remove from nsuserdefaults
        //add to nsuserdefaults
        for (NSString* o in arrayOfCategories)
        {
            NSLog(@"%@",o);
            if([o isEqualToString:cellName]) {

            } else {
                [categoriesSelected addObject:o];
            }

        }
        //set for nsdefaults
        [userDefaults setObject:categoriesSelected forKey:@"categories"];
        [userDefaults synchronize];


            }
    else
    {
        NSLog(@"CHECKING");
        [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;

        //takes away highlight from selection
        [tableView deselectRowAtIndexPath:indexPath animated:YES];

        NSMutableArray *categoriesSelected;

        //add to array
        [categoriesSelected addObject:cellName];

        //retrieve from nsdefaults
        NSMutableArray *arrayOfCategories = [userDefaults objectForKey:@"categories"];

        //add to nsuserdefaults
        for (NSString* o in arrayOfCategories)
        {
            NSLog(@"%@",o);
            [categoriesSelected addObject:o];

        }
        //set for nsdefaults
        [userDefaults setObject:categoriesSelected forKey:@"categories"];
        [userDefaults synchronize];


    }
}

Upvotes: 0

Views: 100

Answers (1)

rmaddy
rmaddy

Reputation: 318834

Change this line, otherwise you have an uninitialized Array:

NSMutableArray *categoriesSelected;

to:

NSMutableArray *categoriesSelected = [[NSMutableArray alloc] init];

Update: After looking at your code there are actually quite a few things that should be improved.

  1. You should load the list of checked categories once in viewDidLoad and keep the list in an instance variable.
  2. It's not a good idea to check to see if a cell is currently checked or not by looking at the cell's accessory type. Your data model should tell you which rows are checked.
  3. You have a lot of duplicate code to toggle the checked state of a cell.
  4. Use a set, not an array, to keep track of the checked cells.

Try the following changes:

Add an NSMutableSet instance variable to your class:

NSMutableSet *_checkedCategories;

In viewDidLoad, load the set:

NSArray *checkedCategories = [[NSUserDefault standardUserDefaults] objectForKey:@"categories"];
if (checkedCategories) {
    _checkedCategories = [[NSMutableSet alloc] initWithArray:checkedCategories];
} else {
    _checkedCategories = [[NSMutableSet alloc] init];
}

Now update your didSelectRow method:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellName = ...; // get the cell name from your data model, not the cell

    BOOL isChecked = [_checkedCategories containsObject:cellName];

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if (isChecked) {
        [_checkedCategories removeObject:cellName]; // no longer checked
        cell.accessoryType = UITableViewCellAccessoryNone;
    } else {
        [_checkedCategories addObject:cellName]; // now checked
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    [[NSUserDefaults standardUserDefaults] setObject:[_checkedCategories allObjects] forKey:@"categories"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

Upvotes: 4

Related Questions