iPhone 应用程序丢失文件

发布于 2024-08-10 06:10:30 字数 1481 浏览 8 评论 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上,重新安装后它可以工作一段时间,但没有出现任何问题。

我们(我和我遇到问题的测试人员)使用 iPhone 3G,版本为 3.1.2。 另一位测试者在他的 iPhone 3GS 3.1.2 上没有遇到这个问题。

有什么想法为什么这个文件会消失吗?

更新

我在代码中发现了错误。有一个代码可以删除整个文档目录。由于这部分代码与远程服务器相关,因此很难追踪该代码。仅在极少数情况下才会出现错误。

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

I am writing an iPhone app – a client for some social network. The app support multiple accounts. Info about accounts are stored in a keyed archive.

A method used for saving:

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

A method uses for reading:

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

The method saveAccounts is used only if some account is added/modified/deleted. The method loadAccounts is used every time the app starts. There isn't any other code that access this file.

I and one of my testers get an issue. At some moment the starts to act like accounts.bin is missing. If loadAccounts returns nil, the app offers to add an account. After I enter an account (the app must call saveAccounts), the app works normally, but when I launch it again, it asks me to add account again. The only solutions is too reinstall the app to iPhone, after reinstall it works for some time with any troubles.

We (I and my tester who get an issue) use iPhone 3G with 3.1.2.
An another tester who didn't experience this issue on his iPhone 3GS with 3.1.2.

Any ideas why this file disappears?

update

I found bug in my code. There was a code that deletes whole Document directory. Because this part of a code is a remote server related, it was hard to trace this code. Bug appeared under very rare conditions only.

Now the bug is found, and the code is corrected. wkw's answer didn't solved my problem, but it forced me to dig deeper. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情话已封尘 2024-08-17 06:10:30

作为调试设备,如何验证 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];

How about -- as a debugging device --verifying the contents of your Documents directory in loadAccounts or at least whenever the unarchiver returns nil. There's some code below to get the names of files in a directory. Set a breakpoint and just dump the NSArray to view the items.
If you can see that the file exists in the Docs dir, then your problem is elsewhere. Perhaps it did not successfully archive. check the return value on the call to archive the data:

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

Get names of files in directory:

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

Perhaps NSUserDefaults might be easier to use?

Also, is there a reason to use Keyed(Un)Archiver instead of NSArray's writeToFile?

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

and to read the file in:

NSMutableArray *accounts = [[NSArray arrayWithContentsOfFile:path] mutableCopy];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文