Tutorial :saving and loading data when app is running



Question:

I would like to have at least 2 arrays which I can create when the user first saves something, and from then on read from the array when the user wants to view that data, and update the data when the user is done updating it.

Does a file need to be created before hand or how is this done on the device during runtime?

Just storing 2 arrays on the device somewhere with the correct path and loading/updating it when needed. I tried a few things, but couldnt seem to get it to work.


Solution:1

I strongly suggest using some sort of database to persist such data, either Core Data or SQLite. With SQLite (my strong point), you can keep the database file open, saving changes to the array transactionally. There is very little chance of anything going wrong, thanks to SQLite's journalling mechanism and its staggeringly thorough testing regime. Core Data is built on SQLite, so the same guarantees apply.

EDIT (RE: comments):

Overkill is only an issue in situations where the cost of the solution is excessive for the problem being solved. SQLite is just sitting around asking to be used. First off, you can create a data structure to represent the data more meaningfully:

@interface Memo {      NSString *title;      NSString *textBody;  };  @property (nonatomic, retain) title;  @property (nonatomic, retain) textBody;  @end    @implementation Memo  @synthesize title, textBody;  @end  

SQLite's raw interface is a bit clunky, so I'd save and load these using a C++ wrapper library to keep things simple:

- (NSString *)databasePath {      NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);      NSString *documentsDir = [documentPaths objectAtIndex:0];      // Choose a filename for your database.      return [documentsDir stringByAppendingPathComponent:@"data.db"];  }    - (void)saveMemos:(NSArray *)memos {      try {          sqlite3_connection con([[self databasePath] cStringUsingEncoding:NSUTF8StringEncoding]);          con.executenonquery("CREATE TABLE IF NOT EXISTS memo (i, title, textBody)");            sqlite3_transaction trans(con);          {              sqlite3_command cmd(con,                  "INSERT INTO memo (i, title, textBody) VALUES (?, ?, ?)");              for (int i = 0; i < memos.count; i++) {                  Memo *memo = (Memo *)[memos objectAtIndex:i];                  cmd.bind(1, i);                  cmd.bind(2, [memo.title cStringUsingEncoding:NSUTF8StringEncoding]);                  cmd.bind(3, [memo.textBody cStringUsingEncoding:NSUTF8StringEncoding]);                  cmd.executenonquery();              }          }          trans.commit();      } catch(exception &ex) {          NSLog(@"SQLite3 error: %s", ex.what());      }  }    - (NSMutableArray *)loadMemos {      sqlite3_connection con([[self databasePath] cStringUsingEncoding:NSUTF8StringEncoding]);      NSMutableArray *result = [NSMutableArray arrayWithCapacity:10];      if (con.executeint("SELECT COUNT(*) FROM sqlite_master WHERE name = 'memo'")) {          sqlite3_command cmd("SELECT title, textBody FROM memo ORDER BY i");          sqlite3_reader rd = cmd.executereader();          while (rd.read()) {              Memo *memo = [[Memo alloc] init];              memo.text = [NSString stringWithFormat:@"%s", rd.getstring(0).c_str()];              memo.titleBody = [NSString stringWithFormat:@"%s", rd.getstring(1).c_str()];              [result addObject:memo];          }      }      return result;  }  

(WARNING: This code is totally untested.)

It is unlikely a home-grown file format will require any less code than this, and it will almost certainly be less robust.

You should also consider Core Data, but I haven't used it myself, so I can't offer assistance on that front.


Solution:2

NSUserDefaults is really, really easy to use to implement persistent data for your application, if your data is in NS* data structures like NSDictionary or NSArray. If your data is not too large then using NSUserDefaults is the way to go. I usually create a "save" method which I call from the app delegate's applicationWillTerminate, and a load method that I call from application:didFinishLaunchingWithOptions:

#define kThing1Key @"thing1"  #define kThing2Key @"thing2"  ...    - (void) save  {      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];        [defaults setObject:self.thing1 forKey:kThing1Key];      [defaults setObject:self.thing2 forKey:kThing2Key];      ...      [defaults synchronize];  }    - (void) load  {      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];        self.thing1 = [defaults objectForKey:kThing1Key];      self.thing2 = [defaults objectForKey:kThing2Key];      ...  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »