14

When I use this method first time it works fine, but when I called it second time I get the error "mutating method sent to immutable object". The problem is at line with "addObject" command.

-(IBAction) save: (id) sender{

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

if (!placesT) {
    placesT=[[[NSMutableArray alloc] init] autorelease];
}

[placesT addObject: [NSString stringWithFormat:@"%@", tagF.text] ];

NSUserDefaults *tUD=[NSUserDefaults standardUserDefaults];
[tUD setObject:placesT forKey:@"placesT"];
[tUD synchronize];

[self dismissModalViewControllerAnimated:YES];

}

James Webster
  • 31,873
  • 11
  • 70
  • 114
gbaor
  • 1,419
  • 3
  • 11
  • 19
  • Well the problem is with the placesT initialization. My bet is the NSUserDefault standard is empty the first time and goes to the second init. You also have a memory leak ther. – Radu Apr 26 '11 at 13:06
  • Note that you can probably replace `[NSString stringWithFormat:@"%@", tagF.text]` with `tagF.text` only. There’s no need to send `+stringWithFormat:` if `text` is already an `NSString`. –  Apr 26 '11 at 23:21

4 Answers4

24

As the documentation for NSUserDefaults says: "Values returned from NSUserDefaults are immutable, even if you set a mutable object as the value." Whenever you want to change a collection you get from NSUserDefaults you have to get the immutable version, make a mutableCopy, modify that, and set it back again.

smorgan
  • 20,228
  • 3
  • 47
  • 55
  • 2
    to add to this that would be for example: someMutableArray = [yourArrayFromDictionary mutableCopy]; hope that helped :) – jimbob Jan 04 '13 at 02:03
10

That is because the object stored in the NSUserDefaults is not the mutableArray but a normal array.

- (IBAction)save:(id)sender {

   NSMutableArray *placesT = nil;
   NSArray *tempArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"placesT"];

   if (tempArray) {
      placesT = [tempArray mutableCopy];
   } else {
      placesT = [[NSMutableArray alloc] init];
   }

   [placesT addObject:[NSString stringWithFormat:@"%@", tagF.text]];

   NSUserDefaults *tUD = [NSUserDefaults standardUserDefaults];
   [tUD setObject:placesT forKey:@"placesT"];
   [tUD synchronize];

   [self dismissModalViewControllerAnimated:YES];
   [placesT release];
}
cutsoy
  • 10,127
  • 4
  • 40
  • 57
rckoenes
  • 69,092
  • 8
  • 134
  • 166
3

placesT is a non mutable array, either always set placesT a mutable object always or use following code.

NSMutableArray *placesT= [[[NSUserDefaults standardUserDefaults] objectForKey:@"placesT"] mutableCopy];
Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Amit Battan
  • 2,968
  • 2
  • 32
  • 68
0

This should work:

-(IBAction) save: (id) sender {

NSMutableArray *placesT= [[NSMutableArray alloc]initWithArray:[[NSUserDefaults standardUserDefaults]

objectForKey:@"placesT"]];

if (!placesT) {
    placesT=[[[NSMutableArray alloc] init] autorelease];
}

[placesT addObject: [NSString stringWithFormat:@"%@", tagF.text] ];

NSUserDefaults *tUD=[NSUserDefaults standardUserDefaults];
[tUD setObject:placesT forKey:@"placesT"];
[tUD synchronize];

[self dismissModalViewControllerAnimated:YES]; }
Asi Givati
  • 1,348
  • 1
  • 15
  • 31