追記:2012/7/16 ソースの誤記を修正しました。
よくある間違いですが、備忘のために記しておきます。iOSアプリを、AppStore経由でアップデートした場合、フォルダのアドレスが変更されます。アプリケーションフォルダの基本パスが変わる訳です。しかし、データ(Documentフォルダの内容、Libraryフォルダの内容)はアップデートの際はコピーされます。それで、アップデート前に、ファイルパスをフルパスで保存していると、アップデートのあとに、ファイルを参照しようとするときに、ファイルが見つからなくなってしまいます。その対応法について記録しておきます。
- まず、正しく保存する
これが,最初から行うべき点ですね。例えば、NSUserDefaultに、ダウンロードした画像のパスを保存するとします。保存先は、ドキュメントフォルダとします。
//保存時
NSString *fileName = @"test.png";
//書き込み
[[reqest responseData] writeToFile:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:fileName] atomically:YES];
//パス保存
NSString *settingPath = [NSString stringWithFormat:@"[DOCUMENTS]/%@",fileName];
[[NSUserDefaults standardUserDefaults] setObject:settingPath forKey:@"FP"];
//読み込み時
NSString *readingPath = [[NSUserDefaults standardUserDefaults] objectForKey:@”FP”];
readingPath = [readingPath stringByReplacingOccurrencesOfString:@”[DOCUMENTS]” withString:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
NSData *deflatedData = [NSData dataWithContentsOfFile:readingPath];
こんな感じですね。実際のパスではなくて、”[DOCUMENTS]”のようなもので代用しておいて、読み込み時に変換する方法ですね。
- 間違えてフルパスを保存してしまった場合
間違えてフルパスを保存してしまって、それでも正しく取りたい場合は、パスの変数名を置換してあげる必要があります。
//保存時
NSString *fileName = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"test.png"];
//書き込み
[[reqest responseData] writeToFile:fileName atomically:YES];
//パス保存 (フルパスを保存してしまった。)
NSString *settingPath = [@"[DOCUMENTS]/%@",fileName];
[[NSUserDefaults standardUserDefaults] setObject:settingPath forKey:@"FP"];
//読み込み時
NSString *readingPath = [[NSUserDefaults standardUserDefaults] objectForKey:@”FP”];
//フルパスを保存してしまっていたら、それ以前を削除する
NSRange rangeLib = [result rangeOfString:@”/Documents/”];
if (rangeLib.location != NSNotFound) {
// フルパスの”Documents”以前を、”[Documents]”に置換して上げる
readingPath = [NSString stringWithFormat:@”[Documents]/%@”,[result substringFromIndex:rangeLib.location+rangeLib.length]];
}
//通常の置換処理
readingPath = [readingPath stringByReplacingOccurrencesOfString:@”[DOCUMENTS]” withString:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
NSData *deflatedData = [NSData dataWithContentsOfFile:readingPath];
この方法の弱点は、@”[Documents]/Documents/test.png”のようなファイルに保存していた時におかしくなってしまいます。その場合は、@”[Documents]”が存在しない事や、@”Mobile Applications”というフォルダがファイルパスの最初に記録されているなどの条件を追加することによって、正しく処理を出来ます。
このように対応することによって,ファイルを正しく扱えるようになります。私も次からは、バグが発生する前に正しく対応したいと思います。
「iOSアプリのアップデート時パスが変わるためファイルパス保存は注意!」への2件のフィードバック