-2

i`m trying to make an NSMutableArray From NSUserDefaults so i can add/delete and edit it later

my code is

- (void)viewDidLoad {
[super viewDidLoad];

NSUserDefaults *ArrayTable = [NSUserDefaults standardUserDefaults];
[ArrayTable setObject:@"One" forKey:@"myArray"];
[ArrayTable setObject:@"Two" forKey:@"myArray"];
[ArrayTable setObject:@"Three" forKey:@"myArray"];
[ArrayTable setObject:@"Four" forKey:@"myArray"];
[ArrayTable setObject:@"Five" forKey:@"myArray"];
[ArrayTable synchronize];

NSMutableArray *array = [[NSMutableArray alloc] init];
array = [ArrayTable objectForKey:@"myArray"];
}


- (void)viewDidUnload
{
    [super viewDidUnload];
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [array count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    cell.textLabel.text = [array objectAtIndex:indexPath.row];
    return cell;
}

when i build and run nothing shows up

i googled it but with no help, i`m sure i didn't understand how to do it

what i need is to build an app that contain a tableview with empty data, the use will fill in the data Add/Delete/Edit

can someone please explain it for me

thank you in advance

aLFaRSi
  • 559
  • 2
  • 12
  • 29
  • 1
    What exactly are you trying to do? You're asking questions about NSUserDefaults, but from your comments it doesn't sound like you need the preferences at all. So describe the actual end-user problem you're trying to solve. – abarnert Jun 14 '12 at 17:52
  • what i need is to build an app that contain a tableview with empty data, the use will fill in the data Add/Delete/Edit @abarnert – aLFaRSi Jun 14 '12 at 18:02
  • So it has nothing to do with the prefs stored in NSUserDefaults at all? You may want to edit the question. – abarnert Jun 14 '12 at 20:57

4 Answers4

2

First, you assigned your array from the user defaults to a local variable named array. Assuming you have a property for this class also named array, this local assignment masks that. If it had not, you would have crashed when you tried to call -count on a string.

The NSUserDefaults object is a dictionary. Each time you call -setObject:forKey: on it, you are actually replacing the object previously set for that key. So at the end of your series of calls to -setObject:forKey:, the resulting value is the NSString Five.

You can't really store a mutable object in the NSUserDefaults, instead you would take a mutable copy of the object when you assign it to your local variable or ivar. To get the behavior you are probably expecting, you should do something like the following:

- (void)viewDidLoad
{
  // Create the array template and store it in NSUserDefaults
  NSArray* arrayTemplate = [NSArray arrayWithObjects:@"One", @"Two", @"Three", @"Four", @"Five", nil];
  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
  [defaults setObject:arrayTemplate forKey:@"myArray"];
  [defaults synchronize];

  // Retrieve a mutable copy of the array from user defaults and assign it to the
  // the property 'array' <- note, this should be an NSMutableArray
  self.array = [[defaults objectForKey:@"myArray"] mutableCopy]; // if not using arc, autorelease this here
}

With that example code, it should behave the way you expected it to behave, and you can continue on. Obviously it makes no sense to set the array in -viewDidLoad and then immediately read a mutable copy. The key thing to keep in mind is that -setObject:forKey: will always replace any object already set for that key. It doesn't add elements or anything like that.

Jason Coco
  • 77,985
  • 20
  • 184
  • 180
1

Your problem is that you are setting a bunch of strings all to the same key:

[ArrayTable setObject:@"yourvalue" forKey:@"myArray"];

just keeps overriding your last value. In order to save an array to your defaults you will have to go about it another way. This question may help you: array to defaults

Community
  • 1
  • 1
rooster117
  • 5,502
  • 1
  • 21
  • 19
1

Since you don't actually want anything to do with the contents of NSUserDefaults, you're just asking how to initialize a mutable array. Here's how to do what you were trying to do:

NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:@"One"];
[array addObject:@"Two"];
[array addObject:@"Three"];
[array addObject:@"Four"];
[array addObject:@"Five"];

Or, more simply:

NSMutableArray *array = [NSMutableArray arrayWithObjects:@"One", @"Two", @"Three", @"Four", @"Five", nil];

(These aren't quite identical. If you're using MRC, the first creates an array that you own and will have to release manually, while the second creates an array that's autoreleased. If you don't understand the difference, the second is better until you learn, but soon you should go learn.)

If you want to know why what you were doing didn't work, here goes:

NSUserDefaults *ArrayTable = [NSUserDefaults standardUserDefaults];

Here you're copying an NSUserDefaults object, which is not an array, or a table; it's a wrapper around the user and system preferences that acts like a dictionary with extra functionality.

[ArrayTable setObject:@"One" forKey:@"myArray"];

This line adds a preference named "myArray" to the user-domain preferences for your application, with the value "One".

[ArrayTable setObject:@"Two" forKey:@"myArray"];
[ArrayTable setObject:@"Three" forKey:@"myArray"];
[ArrayTable setObject:@"Four" forKey:@"myArray"];
[ArrayTable setObject:@"Five" forKey:@"myArray"];

These lines change the value of your "myArray" preference repeatedly, ending with "Five".

[ArrayTable synchronize];

This makes sure that your preference is saved to disk.

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

This creates a new mutable array and stores it in the variable "array".

array = [ArrayTable objectForKey:@"myArray"];

This gets the "five" string out of your preferences and stores it into the variable "array".

This means you've now lost the only reference you had to the actual array.

This also means the static type of the variable no longer matches the dynamic type. When you later call [array count], or [array objectAtIndex:n], you're sending those messages to a string, not an array, so you're probably going to get an exception or other unexpected behavior. (Well, it's pretty much guaranteed that whatever you get is going to be unexpected, since you thought you were talking to an array of 5 objects, not a string.)

abarnert
  • 354,177
  • 51
  • 601
  • 671
0

Create the array and add that to user defaults.

- (void)viewDidLoad {
//...
NSArray * tmpArray = [NSArray arrayWithObjects:@"One",@"Two",@"Three",@"Four", @"Five", nil];

NSUserDefaults *ArrayTable = [NSUserDefaults standardUserDefaults];
[ArrayTable setObject:tmpArray forKey:@"myArray"];
[ArrayTable synchronize];

array = [[ArrayTable objectForKey:@"myArray"] mutableCopy]; 
// array has to be an ivar of your viewcontroller to access it outside of viewDidLoad
// define in your header like @property (nonatomic, strong) NSMutableArray * array;
// with @synthesize array; in the implementation

}

thelaws
  • 7,991
  • 6
  • 35
  • 54
  • i want to create the array from the NSUserDefault, not to save the user defaults from the array – aLFaRSi Jun 14 '12 at 17:27
  • I think you mean `@synthesize`, no? – Jason Coco Jun 14 '12 at 17:33
  • 1
    no :) , what i want is to build an app with a tableview were the user can add/edit and delete data from the table, so i though the way is in using the nsuserdefaults. if there is another way to do it can you please explain it – aLFaRSi Jun 14 '12 at 17:38
  • @H.aLFaRSi In the app you should use the data in an array, and then save that array to userdefaults when the contents change. If you're serious about persisting user data, you should look at coredata. – thelaws Jun 14 '12 at 18:30