在应用程序运行时保存和加载数据

时间:2010-07-13 09:48:15

标签: iphone objective-c serialization

我想在用户第一次保存时创建至少2个数组,然后在用户想要查看数据时从数组中读取数据,并在用户完成更新时更新数据它。

是否需要事先创建文件或在运行时如何在设备上完成?

只需使用正确的路径在设备上存储2个阵列,并在需要时加载/更新它。我尝试了一些东西,但似乎无法让它发挥作用。

2 个答案:

答案 0 :(得分:1)

我强烈建议使用某种数据库来保存这些数据,包括Core Data或SQLite。使用SQLite(我的强项),您可以保持数据库文件处于打开状态,从而以事务方式保存对数组的更改。感谢SQLite的journalling mechanism及其彻底彻底的testing regime,几乎没有出现任何问题的可能性。核心数据建立在SQLite之上,因此适用相同的保证。

编辑(RE:评论):

在解决问题的解决方案成本过高的情况下,过度杀伤只是一个问题。 SQLite只是坐在那里要求使用。首先,您可以创建一个数据结构来更有意义地表示数据:

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

@implementation Memo
@synthesize title, textBody;
@end

SQLite的原始界面有点笨重,所以我使用C++ wrapper library保存并加载它们以保持简单:

- (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;
}

(警告:此代码完全未经测试。)

本土文件格式不太可能需要比这更少的代码,而且几乎肯定不那么健壮。

您还应该考虑核心数据,但我自己没有使用它,所以我不能在这方面提供帮助。

答案 1 :(得分:1)

如果您的数据是NS *数据结构(如NSDictionary或NSArray),NSUserDefaults实际上非常容易用于为您的应用程序实现持久数据。如果您的数据不是太大,那么使用NSUserDefaults就可以了。我通常创建一个“保存”方法,我从应用代表的applicationWillTerminate,调用,并从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];
    ...
}