0

I need to update / add a key -> value pair in a NSMutableArray.

I would like to add a key with a fix value if the key isn't set already.

I tried the following - but the app is crashing at addObject with a "mutating method sent to immutable object" error:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSMutableArray *bookmarks = [defaults mutableArrayValueForKey:@"bookmarks"];

    for (id bookmark in bookmarks) {

        if ([bookmark objectForKey:@"type"] == NULL){
            [bookmark addObject:@"old" forKey:@"type"];
        }
    }

    [[NSUserDefaults standardUserDefaults] synchronize];
1
  • bookmarks is mutable but none of the arrays it contains are mutable. Commented Aug 25, 2015 at 0:09

3 Answers 3

1

Your outer array contains immutable dictionaries. One option would be the following:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *bookmarks = [defaults mutableArrayValueForKey:@"bookmarks"];

[booksmarks enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSDictionary *bookmark, NSUInteger index, BOOL *stop) {
    if (!bookmark[@"type"]) {
        NSMutableDictionary *mutable = [bookmark mutableCopy];
        mutable[@"type"] = @"old";
        [bookmarks replaceObjectAtIndex:index withObject:[mutable copy]];
    }
}];

// Update NSUserDefaults
[[NSUserDefaults standardUserDefaults] setObject:bookmarks forKey:@"bookmarks"];

This should be nice an efficient since it can update multiple dictionaries concurrently.

Sign up to request clarification or add additional context in comments.

Comments

0

Try this:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

//SAVING

NSMutableArray *bookmarksSaving = [NSMutableArray new];

[bookmarksSaving addObject:[[NSMutableDictionary alloc] initWithObjects:@[@"red"] forKeys:@[@"color"]]];
[bookmarksSaving addObject:[[NSMutableDictionary alloc] initWithObjects:@[@"yellow"] forKeys:@[@"color"]]];
[bookmarksSaving addObject:[[NSMutableDictionary alloc] initWithObjects:@[@"green",@"new"] forKeys:@[@"color",@"type"]]];

[defaults setObject:bookmarksSaving forKey:@"bookmarks"];
[[NSUserDefaults standardUserDefaults] synchronize];

//MODIFY

NSMutableArray *bookmarks = [defaults mutableArrayValueForKey:@"bookmarks"];

NSUInteger index = 0;
for (NSDictionary *bookmark in bookmarks) {

    NSMutableDictionary *bookmarkMutable = [bookmark mutableCopy];

    if ([bookmarkMutable objectForKey:@"type"] == nil)
    {
        [bookmarkMutable setValue:@"old" forKey:@"type"];
        [bookmarks replaceObjectAtIndex:index withObject:bookmarkMutable];
    }

    index++;
}

[[NSUserDefaults standardUserDefaults] synchronize];

You have to save your bookmarks as NSMutableDictionary to be able to add/remove keys/value

4 Comments

my values are saved in a NSMutableDicionary: NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:titel, @"titel", code, @"code", @"liga", @"type", nil]; [dataArray addObject:dict];
This is not going to work. Objects saved to user defaults are immutable so you need to make a mutableCopy of the dictionary. You are also modifying but not pushing it back to the array, and not pushing the modified array back to userDefaults so there's a lot missing there.
@Rog okay, so the best way is to create a new NSMutableArray with the updated values and override the userDefaults?
@JacopoPenzo I tried it already, but the app is crashing with this error: [__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object
0
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  NSArray *bookmarks = [defaults objectForKey:@"bookmarks"];
  NSMutableArray *newBookMarks = [bookmarks mutableCopy];
  for (NSDictionary *bookmark in bookmarks) {
    NSMutableDictionary *newBookmark = [bookmark mutableCopy];
    if (![bookmark objectForKey:@"type"]){
      [newBookmark setObject:@"old" forKey:@"type"];
    }
    [newBookMarks addObject:newBookmark];
  }
  [defaults setObject:newBookMarks forKey:@"bookmarks"];
  [defaults synchronize];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.