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.