現在、かなり大きな iPhone アプリケーションを作成しています。とにかく思ったより大きい。アプリケーションの全体的な考え方は、Web サービスから JSON を取得し、それをすべてカスタム NSObject に並べ替えてリンクし、表示することです。
これはすべてうまくいきます。ただし、ユーザーがインターネットに接続していないデバイスでこの情報を表示できるようにするため、提示している情報を各アプリケーションが持つドキュメント フォルダーに保存する必要があります。
私は基本的に、Documents ディレクトリのサブディレクトリに保存するために必要なすべてのカスタム NSObject に NSCoding プロトコルを実装しました。
これはすべて、ここのこの関数によって実現されます。
- (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 のデバッガーがアプリケーションに接続されている場合にのみ、このファイルに格納されているデータを取得できます。が停止するとすぐに、データが破損し、元のデータが含まれなくなります。
データはまだそこに保存されており、作成されたファイルを見ることができますが、ファイル内に保存されている実際のデータ自体が間違っています...
上記のロジックを使用してデータをファイルに保存し、プルして共有オブジェクトを再作成するべきではありませんか? 他の誰かがそのようなことをしようとして成功しましたか? この奇妙な問題に遭遇した理由はありますか? 他の誰かがこの問題を抱えていますか?
それを機能させるためにあらゆる種類のさまざまな方法を試してきましたが、何も達成できませんでした。私ができる必要があるのは、更新が必要になるまで、そこにデータを永続的に保存できることだけです...