2014-06-18 3 views
5

J'essayais d'accéder au répertoire temporaire dans Swift. En Objective-C, je pourrais utiliser le code suivant pour le faire:Accéder au répertoire temporaire dans Swift

- (NSString *)tempDirectory { 

    NSString *tempDirectoryTemplate = 
    [NSTemporaryDirectory() stringByAppendingPathComponent:@"XXXXX"]; 
    const char *tempDirectoryTemplateCString = [tempDirectoryTemplate fileSystemRepresentation]; 
    char *tempDirectoryNameCString   = (char *)malloc(strlen(tempDirectoryTemplateCString) + 1); 
    strcpy(tempDirectoryNameCString, tempDirectoryTemplateCString); 
    char *result        = mkdtemp(tempDirectoryNameCString); 
    if (!result) { 
     return nil; 
    } 
    NSString *tempDirectoryPath = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:tempDirectoryNameCString length:strlen(result)]; 
    free(tempDirectoryNameCString); 
    return tempDirectoryPath; 
} 

Cependant, je suis un peu confondez de la conversion de type et de coulée de Objective-C à Swift, comme const char * ou CMutablePointer<CChar>. Y a-t-il des documents que je devrais examiner?

Merci.

Répondre

10

Que diriez-vous quelque chose comme:

func createTempDirectory() -> String? { 
    let tempDirectoryTemplate = NSTemporaryDirectory().stringByAppendingPathComponent("XXXXX") 

    let fileManager = NSFileManager.defaultManager() 

    var err: NSErrorPointer = nil 
    if fileManager.createDirectoryAtPath(tempDirectoryTemplate, withIntermediateDirectories: true, attributes: nil, error: err) { 
     return tempDirectoryTemplate 
    } else { 
     return nil 
    } 
} 

Il ne répond pas à votre question au sujet de char * mais il est plus propre ...

NSFileManager référence here.

Consultez également this SO question concernant les noms uniques.

+3

Notez que la fonction BSD 'mkdtemp()' est différent de la méthode 'createDirectoryAtPath' NSFileManager, car il crée un nom de répertoire * * unique à partir du modèle donné. –

+0

@Grimxn Merci! Je vais essayer plus tard. BTW semble 'createDirectoryAtPath (chemin: String !, attributs: NSDictionary!)' Est obsolète, maintenant c'est 'createDirectoryAtURL: withIntermediateDirectories: attributes: error:'. Et est-ce que cela signifie que je pourrais utiliser 'createFileAtPath()' pour créer un fichier temporaire avec la même méthode? –

+0

@MartinR donc je devrais créer mon nom unique si j'utilise createDirectoryAtPath? –

2

une traduction directe de votre code Objective-C à Swift serait:

func tempDirectory()->String! { 
    let tempDirectoryTemplate = NSTemporaryDirectory() + "XXXXX" 
    var tempDirectoryTemplateCString = tempDirectoryTemplate.fileSystemRepresentation().copy() 
    let result : CString = reinterpretCast(mkdtemp(&tempDirectoryTemplateCString)) 
    if !result { 
     return nil 
    } 
    let fm = NSFileManager.defaultManager() 
    let tempDirectoryPath = fm.stringWithFileSystemRepresentation(result, length: Int(strlen(result))) 
    return tempDirectoryPath 
} 

Il utilise la même méthode mkdtemp() BSD que votre code d'origine. Cette méthode crée un nom de répertoire à partir du modèle qui est garanti ne pas exister au moment où la méthode est appelée.

Merci à Nate Cook, qui compris que reinterpretCast() peut être utilisé pour traiter le UnsafePointer<CChar> retourné par mkdtemp() comme CString, afin qu'il puisse être transmis à stringWithFileSystemRepresentation(), voir Working with C strings in Swift, or: How to convert UnsafePointer<CChar> to CString.


Au Xcode 6 beta 6, le reinterpretCast() n'est plus nécessaire et le code ci-dessus peut être simplifié à

func tempDirectory()->String! { 
    let tempDirectoryTemplate = NSTemporaryDirectory() + "XXXXX" 
    var tempDirectoryTemplateCString = tempDirectoryTemplate.fileSystemRepresentation() 
    let result = mkdtemp(&tempDirectoryTemplateCString) 
    if result == nil { 
     return nil 
    } 
    let fm = NSFileManager.defaultManager() 
    let tempDirectoryPath = fm.stringWithFileSystemRepresentation(result, length: Int(strlen(result))) 
    return tempDirectoryPath 
} 
8

Swift 2.1 Version:

func createTempDirectory() -> String? { 

    let tempDirURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent("XXXXXX") 

    do { 
     try NSFileManager.defaultManager().createDirectoryAtURL(tempDirURL, withIntermediateDirectories: true, attributes: nil) 
    } catch { 
     return nil 
    } 

    return tempDirURL.absoluteString 
} 
3

Swift 3 version

func createTempDirectory() -> String? { 

    guard let tempDirURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("myTempFile.xxx") else { 
     return nil 
    } 

    do { 
     try FileManager.default.createDirectory(at: tempDirURL, withIntermediateDirectories: true, attributes: nil) 
    } catch { 
     return nil 
    } 

    return tempDirURL.absoluteString 
} 
+0

Quelques choses pour d'autres personnes voulant utiliser ceci: 1> Vous avez fait une URL avec une extension de fichier, et créez un dossier, et 2>, cela retournera zéro si le répertoire existe déjà, ce qui pourrait Soyez le comportement que vous (et l'affiche originale) voulez, mais dans la plupart des cas, l'utilisateur voudra probablement un résultat même si le répertoire existe déjà. (Ces deux choses n'ont pas été testées, mais à moins que Swift ne se comporte différemment d'Obj-C, voici les résultats auxquels je m'attendrais) – narco

2

Swift 3 et jusqu'à

Je pense qu'une bonne façon de le faire est en rapide avec une extension sur FileManager. Cela devrait créer un dossier temporaire unique et vous renvoyer l'URL.

extension FileManager{ 

    func createTemporaryDirectoy() throws -> URL{ 
     let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) 

     try self.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) 
     return url 
    } 
} 
Questions connexes