0

I am new to iOS development and could not find a way to solve this problem:

I have an app that has two views: one where the user enters some information (say a string), and another view where there is a tableview that includes all the strings that were ever entered (like a history view).

What I am trying to find is a good way to store the input string, then load it into the table view data source once the user switches to the history. I tried to use NSUserdefault but with not much success. Just getting messed up with the data structures, etc.

Here is what I am doing on the main view (where the user enters the input string):

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];     
    NSMutableArray *arr1 = [[NSMutableArray alloc] init];
    arr1 = [defaults arrayForKey:@"historyNames"];

    [arr1 addObject:string];

    [defaults setObject:arr1 forKey:@"historyNames"];    

From some reason I get a warning where I read to arr1, and honestly, I doubt that should work anyway.

Can anyone suggest how I could modify this to work properly and achieve what I am looking for?

Thanks.

moshikafya
  • 3,190
  • 5
  • 22
  • 27
  • If this is the place where the user input data, what are you reading from [defaults arrayForKey:@"historyNames"]; that line where you have the warning. In fact, the warning comes because there is not anything stored in [NSUserDefaults standardUserDefaults]; in that moment – Teofilo Israel Vizcaino Rodrig May 18 '12 at 19:53

2 Answers2

7
[defaults arrayForKey:@"historyNames"];

Will return nil if you never initialized and saved an array for that key in NSUSerDefaults.

If you initialize and array and set it once (look up how to initialize default values for NSUserDefaults), it will return a proper array.

Then you can just do

NSMutableArray *arr1  = [NSMutableArray arrayWithArray:[[defaults arrayForKey@"historyNames"]];

Depending on how many elements this array will have, you may be better off using Core Data. Using user defaults is not very efficient for many/large values, just for small settings and things like that.

Dima
  • 23,484
  • 6
  • 56
  • 83
  • It has never been necessary to invoke `-[NSUserDefaults synchronize]` unless you think some other program may be consulting your preferences or if you expect your app to crash rather than terminating gracefully. Furthermore, Apple discourages it. `NSUserDefaults` will automatically synchronize periodically and that should be sufficient for normal cases. – Ken Thomases May 19 '12 at 16:42
0

When your application starts up, look in user defaults to see if you have an array object already from the last time you used it. If there isn't one, call alloc and init for arr1. (You don't want to call it if you're accessing it from defaults.)

NSMutableArray * arr1;
arr1 = (NSMutableArray *) [defaults objectForKey:@"historyNames"];
if (!arr1) {
    arr1 = [[NSMutableArray alloc] initWithCapacity:20];
}

In your main view, just add the input string, and save the defaults.

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject: arr1 forKey: @"historyNames"];
[prefs synchronize];
Owen Hartnett
  • 5,925
  • 2
  • 19
  • 35
  • where do you add the additional item to the array before storing? what is 20? what if I dont want to limit myself? – moshikafya May 18 '12 at 19:55
  • Just call [arr1 addObject:string] as you did before. 20 is just a best guess amount of how big the array will get, you can use your own number, iOS won't hold you to it. – Owen Hartnett May 18 '12 at 19:58
  • you can ignore the initWithCapacity bit, it actually isn't necessary. – Dima May 18 '12 at 20:00
  • some details on capacity [here](http://stackoverflow.com/questions/3948062/nsmutablearray-initwithcapacity-nuances) showing that it is not important in most cases. – Dima May 18 '12 at 20:01
  • This will not work as `objectForKey:` returns an immutable object. You will need to make it mutable by calling `mutableCopy` or creating a new mutable array with the contents of the array returned. Simply casting will have no effect on the object apart from lying to the compiler and making it believe it has a mutable array when it does not. – Paul.s May 18 '12 at 20:17