Overwriting NSMutableArray loaded from NSUserDefaults

45 views Asked by At

So I'm having real problems overwriting an array stored in NSUSerDefaults. Basically I have a checklist of 100 items (defined by bools in an array(which are actually strings at the moment)) and I need to save if each item is checked so when the app loads, the checklist remains as it was before the app was closed.

I'll try my best to explain the current process.

In the ViewDidLoad, I create empty Array boolArrayOfCheckList:

boolArrayOfCheckList = [[NSMutableArray alloc] initWithCapacity:100];
    for (NSInteger i = 0; i < 100; i++){
        [boolArrayOfCheckList addObject:[NSString stringWithFormat:@"NO"]];
    }

So currently, the array suggests no items are checked as 100 indexes are set to @"NO".

Then I load the array from NSUserDefaults into the above array:

NSMutableArray *boolArrayOfCheckList = [[NSUserDefaults standardUserDefaults] objectForKey:@"myBoolArray"];

Then I set the state of a switch button based on the Array index value associated with the switch button (for example this is button 1, stored at index 0):

if([[boolArrayOfCheckList objectAtIndex:0] isEqualToString:@"YES"]){
   [switchButton1 setOn:YES];  //array says YES, so button is on
}
else {
   [switchButton1 setOn:NO];  //array says NO, so remains off
}

This seems to work on the first go, and saving the array. But the problem comes if a element within the array is changed, because it doesn't save any previously stored changes...

If another switch is pressed e.g. Switch 2:

- (IBAction)Switch2:(id)sender {
    if([switchButton2 isOn]){
        [boolArrayOfCheckList replaceObjectAtIndex:1 withObject:[NSString stringWithFormat:@"YES"]];
        [self SaveDataWhenArrayInBoolArrayIsChanged]; //save data to YES
    }
    else{
        [boolArrayOfCheckList replaceObjectAtIndex:1 withObject:[NSString stringWithFormat:@"NO"]];
        [self SaveDataWhenArrayInBoolArrayIsChanged]; //save data to NO
    }
}

If a button is pressed, changing the state of a button, the SaveDataWhenArrayInBoolArrayIsChanged method is called, and saves to NSUserDefaults like this:

[[NSUserDefaults standardUserDefaults] setObject:boolArrayOfCheckList forKey:@"myBoolArray"];
[[NSUserDefaults standardUserDefaults] synchronize];

But for some reason, if for example I have buttons 1, 3 and 5 on when the app is launched, then I click button 4 to be ON, making 1, 3, 4, 5 buttons on, when I go back, only button 4 is on and it resets buttons 1, 3 and 5 :(

Is there an easier solution to this? Or do i need to change my implmentation or make a copy of the array and save the copy of something? If so, how? Thank you.

Update

I followed this guys post HERE.

I think I may have fixed the issue, when loading the array from NSUserDefaults, I loaded it into a temp array (because it must be immutable), then copied the temp array into the empty boolArrayOfChecklist (which is a new mutable array) like this:

NSMutableArray *boolArrayOfCheckList_Temp = (NSMutableArray *)[[NSUserDefaults standardUserDefaults] objectForKey:@"myBoolArray"];
boolArrayOfCheckList = [NSMutableArray arrayWithArray:boolArrayOfCheckList_Temp];

Not sure thats what I was supposed to do, but it allows me to edit the saved array, save it and reload it without previous elements/indexes being reset.

So it seems to be working... and I know I shouldn't be using strings and I should wrap bools or use NSNumber but I'm unsure how these work with MutableArrays and comparing them... I'm sure there a much better why than the way I'm doing it but I'm still learning/a beginner... If someone would like to show me though, that would be great :)

1

There are 1 answers

1
Wain On BEST ANSWER

You should be using NSNumber, then you don't need to worry about comparison as such because you just extract the flag value and set it as the switch state.

Also, you don't want to create the array explicitly and try to restore it from defaults. Instead you should be registering defaults and loading defaults (note that you will need to write code if the number of items changes in the future to migrate...):

NSMutableArray  *checklistDefaults = [[NSMutableArray alloc] initWithCapacity:100];
for (NSInteger i = 0; i < 100; i++){
    [checklistDefaults addObject:@NO];
}

[[NSUserDefaults standardUserDefaults] registerDefaults:@{@"myBoolArray" : checklistDefaults}];

Then load it to your array for usage:

NSMutableArray *boolArrayOfCheckList = [[[NSUserDefaults standardUserDefaults] objectForKey:@"myBoolArray"] mutableCopy];

Then use and update the values:

[switchButton1 setOn:[[boolArrayOfCheckList objectAtIndex:XX] boolValue]];

BOOL currentValue = [[boolArrayOfCheckList objectAtIndex:XX] boolValue];
[boolArrayOfCheckList replaceObjectAtIndex:XX withObject:@( !currentValue )];