0

我正在编写一个 iPhone 应用程序——某个社交网络的客户端。该应用程序支持多个帐户。有关帐户的信息存储在密钥存档中。

一种用于保存的方法:

- (void) saveAccounts {
 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *path = [paths objectAtIndex:0];
 path = [path stringByAppendingPathComponent:@"accounts.bin"];
 // NSMutableArray *accounts = ...;
 [NSKeyedArchiver archiveRootObject:accounts toFile:path];
}

一种用于阅读的方法:

- (NSMutableArray *) loadAccounts {
 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *path = [paths objectAtIndex:0];
 path = [path stringByAppendingPathComponent:@"accounts.bin"];
 NSMutableArray *restoredAccounts = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
 return [restoredAccounts retain];
}

该方法saveAccounts仅在添加/修改/删除某些帐户时使用。loadAccounts每次应用程序启动时都会使用该方法。没有任何其他代码可以访问此文件。

我和我的一位测试人员遇到了问题。在某个时刻,开始表现得好像accounts.bin消失了。如果loadAccounts返回nil,应用程序会提供添加帐户。输入账号后(应用程序必须调用saveAccounts),应用程序正常运行,但是当我再次启动它时,它要求我再次添加帐户。唯一的解决方案是将应用程序重新安装到 iPhone 上,重新安装后它可以运行一段时间并出现任何问题。

我们(我和我的测试人员遇到问题)使用 3.1.2 的 iPhone 3G。另一位测试人员在使用 3.1.2 的 iPhone 3GS 上没有遇到此问题。

任何想法为什么这个文件会消失?

更新

我在我的代码中发现了错误。有一个代码可以删除整个 Document 目录。因为这部分代码是与远程服务器相关的,所以很难追踪到这段代码。错误仅在非常罕见的情况下出现。

现在发现了bug,并更正了代码。wkw的回答并没有解决我的问题,但它迫使我更深入地挖掘。谢谢!

4

1 回答 1

0

怎么样——作为调试设备——验证 loadAccounts 中 Documents 目录的内容,或者至少在 unarchiver 返回 nil 时验证。下面有一些代码可以获取目录中文件的名称。设置断点并转储 NSArray 以查看项目。
如果您可以看到该文件存在于 Docs 目录中,那么您的问题出在其他地方。也许它没有成功存档。检查调用的返回值以存档数据:

if( ! [NSKeyedArchiver archiveRootObject:accounts toFile:path] ){
    NSLog(@"Oooops! account data failed to write to disk");
}

获取目录中文件的名称:

- (NSArray*) directoryContentsNames:(NSString*) directoryPath {
    NSArray* result;
    {
        result = [[NSFileManager defaultManager]
            directoryContentsAtPath: directoryPath];
    }
    if( result && [result count] > 0 ){
        NSMutableArray *items = [[[NSMutableArray alloc] init] autorelease];
        for( NSString *name in result ){
            if( ! [name isEqualToString:@".DS_Store"] )
                [items addObject: name];
        }
        result = items;

    }
    return result;
}

也许 NSUserDefaults 可能更容易使用?

另外,是否有理由使用 Keyed(Un)Archiver 而不是 NSArray 的 writeToFile?

if( ! [accounts writeToFile:path atomically:YES] )
    ; // do something since write failed

并读取文件:

NSMutableArray *accounts = [[NSArray arrayWithContentsOfFile:path] mutableCopy];
于 2009-11-08T19:18:52.363 回答