web-dev-qa-db-ja.com

iPhoneで書き込み可能なパスを取得するにはどうすればよいですか?

この質問を投稿しているのは、別の投稿のために書かれたこの質問に対する完全な回答があったためです。したがって、私はこれをコミュニティWikiにして、他の人が質問と回答を具体化できるようにしました。答えが役に立つと思う場合は、質問に投票してください-コミュニティWikiであるため、この投票でポイントを獲得すべきではありませんが、他の人が見つけるのに役立ちます

IPhoneでファイル書き込みが許可されるパスを取得するにはどうすればよいですか?シミュレータ上で(誤解を招くように)好きな場所に書き込むことができますが、iPhoneでは特定の場所にしか書き込むことができません。

考慮すべき3種類の書き込み可能なパスがあります。1つ目はドキュメントです。保存したいものを保存し、iTunesを通じてユーザーが利用できるようにします(3.2以降)。

_NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
_

次に、Documentsディレクトリに非常によく似た、Libraryフォルダがあります。このフォルダには、構成ファイルと書き込み可能なデータベースも保存しますが、iTunesを介してユーザーが混乱することは望ましくありません。

_NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDirectory = [paths objectAtIndex:0];
_

ユーザーが3.2(iPad)よりも古いデバイスを使用してiTunesでファイルを表示できない場合でも、NSLibraryDirectory定数はiPhoneOS 2.0以降で使用可能であるため、3.0(またはまだ実行中の場合はそれ以前)それ)。また、ユーザーがドキュメントを変更できるようにアプリにフラグを立てない限り、ユーザーは何も見ることができません。そのため、今日ドキュメントを使用している場合、ユーザードキュメントのサポートのために更新するときに場所を変更する限り問題ありません。

最後に、キャッシュディレクトリがあります。ここには、長期にわたって存在するかどうかを気にしない画像を置くことができます(電話はある時点でそれらを削除する場合があります)。

_NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachePath = [paths objectAtIndex:0];
BOOL isDir = NO;
NSError *error;
if (! [[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO) {
    [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:&error];
}
_

そこに実際にCachesディレクトリを作成しなければならないことに注意してください。そのため、作成時には毎回チェックして作成する必要があります。ちょっと痛いけど、そういう風に。

次に、書き込み可能なパスがある場合、次のようにファイル名を追加します。

_NSString *filePath =  [documentsDirectory stringByAppendingPathComponent:@"SomeDirectory/SomeFile.txt"];
_

または

_NSString *filePath =  [cachePath stringByAppendingPathComponent:@"SomeTmpFile.png"];
_

そのパスを読み取りまたは書き込みに使用します。

上記のサンプル文字列の1つが使用している(作成済みの場合)書き込み可能なパスのいずれかにサブディレクトリを作成できることに注意してください。

画像を写真ライブラリに書き込もうとする場合、ファイルシステムコールを使用してこれを行うことはできません。代わりに、メモリにUIImageを用意し、UIKitで定義されたUIImageWriteToSavedPhotosAlbum()関数呼び出しを使用する必要があります。宛先形式または圧縮レベルを制御することはできず、この方法でEXIFを付加することはできません。

上記のKendall&Daveに感謝します。この修正案は役立つと思いました。一度限りのデバッグコードを使用する場合、マイクアッシュの NSBlogthis trick を使用して、一時変数isDir&errorを削除し、行数を最小限に抑えて冗長性をほぼ高めました耐えられる:

NSFileHandle *dumpFileHandle = nil;
#ifdef DEBUG
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&(BOOL){0}])
        [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:YES attributes:nil error:&(NSError*){nil}];
    NSString *dumpPath = [cachePath stringByAppendingPathComponent:@"dump.txt"];
    [[NSFileManager defaultManager] createFileAtPath:dumpPath contents:nil attributes:nil];
    [(dumpFileHandle = [NSFileHandle fileHandleForWritingAtPath:dumpPath]) truncateFileAtOffset:0];
#endif

if (dumpFileHandle) [dumpFileHandle writeData:blah];
5
Pierre Houston