1

I saved a nsmutableArray inside a NSUserDefaults.

In the following case, it seems that all the elements from the array are equal to 0, even though in this case position 1 and position 5 should have 1 instead of 0 as a value. I know that NSUserDefaults elements are immutable but ...I did add that mutableCopy when retrieving the value.

Where am I wrong?

//create array

NSMutableArray *objArray = [[NSMutableArray alloc] init];
        for (int i=0; i< 100;i++) [objArray addObject:@"0"];
        [objArray replaceObjectAtIndex:1 withObject:@"1"];
        [[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];

// update

elementPosition = 5;
 NSMutableArray *objArray = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]] mutableCopy];
        [objArray replaceObjectAtIndex:elementPosition withObject:@"1"];


//check the array


NSMutableArray *objArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:nameFile]];
    BOOL displayContent = true;


for (int i=0; i<[objArray count];i++)
{

if ([[objArray objectAtIndex:i] isEqualToString:@"0"])
{
    displayContent = false;
}
}
just ME
  • 1,817
  • 6
  • 32
  • 53

4 Answers4

2

I think when you retrieve and your mutable array from UserDefault and updated but you didn't set that new updated object to UserDefault, its having the old object which was set before. you have to store your update array again to userdefault with same key which update your UserDefautlt.

elementPosition = 5;
 NSMutableArray *objArray = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]] mutableCopy];
        [objArray replaceObjectAtIndex:elementPosition withObject:@"1"];
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];
Retro
  • 3,985
  • 2
  • 17
  • 41
1

You should call the synchronize method

[[NSUserDefaults standardUserDefaults] synchronize];
Suhail kalathil
  • 2,673
  • 1
  • 13
  • 12
  • why should I do that? – just ME Jun 30 '14 at 09:07
  • You should call this after 'set' object to user defaults. – LLIAJLbHOu Jun 30 '14 at 09:09
  • >synchronize Writes any modifications to the persistent domains to disk and updates all unmodified persistent domains to what is on disk. - (BOOL)synchronize Return Value YES if the data was saved successfully to disk, otherwise NO. Discussion Because this method is automatically invoked at periodic intervals, use this method only if you cannot wait for the automatic synchronization (for example, if your application is about to exit) or if you want to update the user defaults to what is on disk even though you have not made any changes. – Suhail kalathil Jun 30 '14 at 09:11
  • so should I use this synchronize or not? – just ME Jun 30 '14 at 12:18
  • You no longer need to invoke `synchronize`. As stated in the `NSUserDefaults` documentation: >> *The synchronize() method, which is automatically invoked at periodic intervals, keeps the in-memory cache in sync with a user’s defaults database.* – tomacco Sep 19 '16 at 10:01
1

I think you should fix your code follow my bellow code:

[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];
[[NSUserDefaults standardUserDefaults] synchronize];

...

NSMutableArray *objArray = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]] mutableCopy];
[objArray replaceObjectAtIndex:elementPosition withObject:@"1"];
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:nameFile];
[[NSUserDefaults standardUserDefaults] synchronize];
0

Replace your code with this:

//create array

NSMutableArray *objArray = [[NSMutableArray alloc] init];
for (int i=0; i< 100;i++){
    [objArray addObject:@"0"];
}
[objArray replaceObjectAtIndex:1 withObject:@"1"];
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];

//First mistake. Missing this. Without this line the data is not saved in NSUserDefaults
[[NSUserDefaults standardUserDefaults] synchronize];

// update

elementPosition = 5;
NSMutableArray *objArray = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]] mutableCopy];
[objArray replaceObjectAtIndex:elementPosition withObject:@"1"];

//Second Mistake. You did not update the NSUserDefaults again.
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];
[[NSUserDefaults standardUserDefaults] synchronize];




//check the array
NSMutableArray *objArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]];
BOOL displayContent = true;


for (int i=0; i<[objArray count];i++)
{

    if ([[objArray objectAtIndex:i] isEqualToString:@"0"])
    {
        displayContent = false;
    }

   //Third mistake. Once the BOOL is made false in an if block you have to make it true in the else block, otherwise the value of the BOOL will remain false even if it does not enter the if block.
    else{
        displayContent = true;
    }
    NsLog(@"ArrayIndex=[%d];DisplayContent=[%d]",i,displayContent);
}

Happy coding.

  • Why do i need to use that synchronize? I ve made some tests and it seems that NUserDefault array is saved without that synchronize. And secondly retarding that third mistake, i need a bool value to be false in case there is one object in the array for which the value is 0 instead of 1. – just ME Jun 30 '14 at 12:23
  • The synchronize method is automatically invoked at periodic intervals. But we want to saved the data immediately and not wait for automatic synchronization(for example, if your application is about to exit) or if you want to update the user defaults to what is on disk even though you have not made any changes. – try catch finally Jul 01 '14 at 04:41
  • Check this: https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/nsuserdefaults_class/reference/reference.html#//apple_ref/occ/instm/NSUserDefaults/synchronize – try catch finally Jul 01 '14 at 04:41
  • Regarding the third mistake, I m not sure what you wanted to do there. Since you already populated the array with "0" first. Then at index 1 & 5 you inserted "1". So the BOOL value will be false because once it enters the if block, for the seconde index, the bool value will not change anymore, if there is no else block, so your bool value will always be false. – try catch finally Jul 01 '14 at 05:04
  • Check this answer too : http://stackoverflow.com/questions/9647931/nsuserdefaults-synchronize-method/9647965#9647965 – try catch finally Jul 01 '14 at 05:24
  • The benefit to calling synchronize more often is if your application may crash and the information you are saving is important, otherwise iOS will save it for you periodically. – try catch finally Jul 01 '14 at 05:25