我究竟做错了啥? NSFileManager 问题
Posted
技术标签:
【中文标题】我究竟做错了啥? NSFileManager 问题【英文标题】:What am I doing wrong? NSFileManager woes我究竟做错了什么? NSFileManager 问题 【发布时间】:2011-11-03 15:09:08 【问题描述】:我目前正在构建一个相当大的 iPhone 应用程序。反正比我预期的要大。但这不是重点,该应用程序的总体思路是从 Web 服务中获取 JSON,将其全部分类为自定义 NSObject,这些 NSObject 链接在一起然后呈现。
一切顺利。但是,因为我希望用户能够在没有互联网连接的情况下在设备上看到这些信息,所以我需要将我呈现的信息保存到每个应用程序的 Documents 文件夹中。
我基本上将 NSCoding 协议实现到所有需要它的自定义 NSObject 中,以便将其保存到 Documents 目录的子目录中。
这里都是通过这个函数来实现的。
- (void)applicationDidEnterBackground:(UIApplication *)application
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Data"];
NSString *dataFileString = [dataPath stringByAppendingPathComponent:@"Company.archive"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataFileString]) //Does directory already exist?
MACompany *company = [MACompany sharedMACompany];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Data"];
NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) //Does directory already exist?
if (![[NSFileManager defaultManager] createDirectoryAtPath:dataPath
withIntermediateDirectories:NO
attributes:nil
error:&error])
NSLog(@"Create directory error: %@", error);
NSString *dataFileString = [dataPath stringByAppendingPathComponent:@"Company.archive"];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:company forKey:@"MACompany"];
[archiver finishEncoding];
[[NSFileManager defaultManager] createFileAtPath:dataFileString
contents:data
attributes:nil];
[archiver release];
[data release];
else
NSLog(@"File already exists, no need to recreate, not yet anyway");
当用户首次加载应用程序 (application didFinishLaunchingWithOptions:
) 和用户在后台打开应用程序 (applicationWillEnterForeground:
) 时,我执行以下请求。
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Data"];
NSString *dataFileString = [dataPath stringByAppendingPathComponent:@"Company.archive"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataFileString]) //Does directory already exist?
NSLog(@"Create a new Company Request");
MAWebRequests *companyReq = [[MAWebRequests alloc] init];
[companyReq getCompanyDetails];
[companyReq release];
else
NSLog(@"Saved Company Needs to be Decoded applicationWillEnterForeground");
MACompany *company = [MACompany sharedMACompany];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Data"];
NSString *dataFileString = [dataPath stringByAppendingPathComponent:@"Company.archive"];
NSData *data = [[NSData alloc] initWithContentsOfFile:dataFileString];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[data release];
company = [unarchiver decodeObjectForKey:@"MACompany"];
[unarchiver finishDecoding];
[unarchiver release];
现在这一切都很好,我也可以从这个文件中提取。但是,当我将 Xcode 的调试器附加到应用程序时,我只能获取存储在此文件中的数据。一旦停止,数据就会损坏并且不包含原始数据。
数据仍然存储在那里,我可以看到创建的文件,但是存储在文件中的实际数据本身是错误的......
我不应该使用上述逻辑将数据保存到文件中,然后再拉取重新创建共享对象吗? 有没有其他人试图做这样的事情并取得了成功? 我遇到这个奇怪的问题有什么原因吗? 有其他人遇到过这个问题吗?
任何帮助将不胜感激,一直在尝试各种不同的方法来使其工作,但没有任何帮助。我需要做的就是能够将数据永久存储在那里,直到我需要更新它......
【问题讨论】:
[MAWebRequests alloc];
听起来很糟糕。你忘记init
了吗?此外,如果您需要在启动之间保留大量数据,您应该考虑使用 CoreData 或 SQLite...
我确实忘记初始化了,谢谢!清理了那一点,但仍然没有解决我的问题......已经跟踪了我正在保存的数据大小,3kb,一点也不大! :)
好的,请相应地更新您的帖子。无论如何,您已经粘贴在这里的代码看起来不错。您需要发布对事物进行编码和解码的代码。您还应该在 Xcode 中运行“Analyze”(位于 Build 菜单下方)并更正您的代码以删除所有警告。
您的保存代码是否可能需要很长时间才能完成。操作系统只给你几秒钟的时间从applicationDidEnterBackground:
返回,然后它会因为没有响应而终止你的应用程序(除非附加了调试器)。
@OleBegemann 我认为你可能是对的,尝试在其他地方实现它来编码和保存菜单。谢谢!
【参考方案1】:
我已经通过在 applicationDidEnterBackground 之前保存 MACompany 对象解决了这个问题:
非常感谢@OleBegemann 帮助找到问题的嵌套位置。
【讨论】:
以上是关于我究竟做错了啥? NSFileManager 问题的主要内容,如果未能解决你的问题,请参考以下文章