web-dev-qa-db-fra.com

Créer un dossier / répertoire dans Objective-C / cocoa

J'ai ce code pour créer un dossier/répertoire dans Objective-C/cocoa.

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

Cela fonctionne bien, mais j'ai obtenu creatDirectoryAtPath:attributes is deprecated message d'alerte. Quelle est la nouvelle façon de créer un constructeur d'annuaire dans Cocoa/Objective-c?

RESOLU

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

Votre solution est correcte, bien que Apple inclut une note importante dans 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;

Essentiellement, si plusieurs threads/processus modifient simultanément le système de fichiers, l'état peut changer entre les appels de fileExistsAtPath:isDirectory: et appeler createDirectoryAtPath:withIntermediateDirectories:, il est donc superflu et peut-être dangereux d'appeler fileExistsAtPath:isDirectory: dans ce contexte.

Pour vos besoins et dans la portée limitée de votre question, ce ne serait probablement pas un problème, mais la solution suivante est à la fois plus simple et offre moins de chance de problèmes futurs:

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);
}

Notez également de documentation d'Apple :

Valeur de retour

OUI si le répertoire a été créé, OUI si createIntermediates est défini et que le répertoire existe déjà), ou NON si une erreur s'est produite.

Ainsi, définir createIntermediates sur YES, ce que vous faites déjà, est une vérification de facto de l'existence du répertoire.

18
Matt

Je pensais ajouter à cela et en mentionner un peu plus dans la documentation sur l'utilisation de la méthode + defaultManager:

Dans iOS et Mac OS X v 10.5 et versions ultérieures, vous devriez envisager d'utiliser [[NSFileManager alloc] init] plutôt que la méthode singleton defaultManager. Les instances de NSFileManager sont considérées comme thread-safe lorsqu'elles sont créées à l'aide de [[NSFileManager alloc] init] .

3
August

Vous pouvez préférer travailler avec la méthode NSFileManager:

createDirectoryAtURL:withIntermediateDirectories:attributes:error:

Il fonctionne avec des URL au lieu de chaînes de chemin.

2
Stephan