web-dev-qa-db-ja.com

Objective-C / cocoaにフォルダー/ディレクトリを作成します

Objective-C/cocoaにフォルダー/ディレクトリを作成するためのこのコードがあります。

if(![fileManager fileExistsAtPath:directory isDirectory:&isDir])
        if(![fileManager createDirectoryAtPath:directory attributes:nil])
            NSLog(@"Error: Create folder failed %@", directory);

正常に動作しますが、creatDirectoryAtPath:attributes is deprecated警告メッセージ。 Cocoa/Objective-cでディレクトリビルダーを作成する最新の方法は何ですか?

解決済み

BOOL isDir;
NSFileManager *fileManager= [NSFileManager defaultManager]; 
if(![fileManager fileExistsAtPath:directory isDirectory:&isDir])
    if(![fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:NULL])
        NSLog(@"Error: Create folder failed %@", directory);
44
prosseek
53
Dave DeLong

ソリューションは正しいですが、AppleにはNSFileManager.h内に重要な注意事項が含まれています:

/* The following methods are of limited utility. Attempting to predicate behavior 
based on the current state of the filesystem or a particular file on the 
filesystem is encouraging odd behavior in the face of filesystem race conditions. 
It's far better to attempt an operation (like loading a file or creating a 
directory) and handle the error gracefully than it is to try to figure out ahead 
of time whether the operation will succeed. */

- (BOOL)fileExistsAtPath:(NSString *)path;
- (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory;
- (BOOL)isReadableFileAtPath:(NSString *)path;
- (BOOL)isWritableFileAtPath:(NSString *)path;
- (BOOL)isExecutableFileAtPath:(NSString *)path;
- (BOOL)isDeletableFileAtPath:(NSString *)path;

基本的に、複数のスレッド/プロセスがファイルシステムを同時に変更している場合、fileExistsAtPath:isDirectory:の呼び出しとcreateDirectoryAtPath:withIntermediateDirectories:の呼び出しの間で状態が変わる可能性があるため、このコンテキストでfileExistsAtPath:isDirectory:を呼び出すことは不要であり、おそらく危険です。

あなたのニーズに対して、そしてあなたの質問の限られた範囲内でそれは問題ではないでしょうが、次の解決策はより単純であり、将来の問題が発生する可能性が低くなります:

NSFileManager *fileManager= [NSFileManager defaultManager];
NSError *error = nil;
if(![fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:&error]) {
     // An error has occurred, do something to handle it
     NSLog(@"Failed to create directory \"%@\". Error: %@", directory, error);
}

Appleのドキュメント からも注意してください:

戻り値

ディレクトリが作成された場合はYES、createIntermediatesが設定されていてディレクトリが既に存在する場合はYES)、エラーが発生した場合はNO。

したがって、createIntermediatesYESに設定することは、既に行っていますが、ディレクトリが既に存在するかどうかの事実上のチェックです。

18
Matt

私はこれに追加し、+ defaultManagerメソッドの使用に関するドキュメントからもう少し言及すると思いました:

iOSおよびMac OS X v 10.5以降では、シングルトンメソッドdefaultManagerではなく[[NSFileManager alloc] init]の使用を検討する必要があります。NSFileManagerのインスタンスは、[[NSFileManager alloc] init] 。

3
August

NSFileManagerメソッドを使用することをお勧めします。

createDirectoryAtURL:withIntermediateDirectories:attributes:error:

パス文字列ではなくURLで機能します。

2
Stephan