Доступ к временному каталогу в Swift
Я пытался получить доступ к временному каталогу в Swift. В Objective-C я мог бы использовать следующий код для этого:
- (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;
}
Тем не менее, я немного запутался в преобразовании типов и приведении типов из Objective-C в Swift, таких как const char *
или же CMutablePointer<CChar>
, Есть ли какие-либо документы, которые я должен изучить?
Благодарю.
5 ответов
Как насчет чего-то вроде:
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
}
}
Он не отвечает на ваш вопрос о char*, но он чище...
Ссылка NSFileManager здесь.
Также проверьте этот ТАК вопрос относительно уникальных имен.
Согласно Apple, использование NSTemporaryDirectory
не рекомендуется:
См. URL-адрес метода FileManager (for:in: Соответствующий For:create:) для получения информации о предпочтительных способах поиска правильного временного каталога. Для получения дополнительной информации о временных файлах см. Руководство по программированию файловой системы.
Поэтому вместо этого вы должны использовать FileManager.default.temporaryDirectory
или если вам нужен уникальный путь:
let extractionPath = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
ВерсияSwift 2.1:
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 с расширением на FileManager. Это должно создать уникальную временную папку и вернуть вам 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
}
}
ВерсияSwift 3
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
}
Прямой перевод вашего кода Objective-C в Swift:
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
}
Он использует то же самое mkdtemp()
Метод BSD как ваш оригинальный код. Этот метод создает имя каталога из шаблона, который гарантированно не существует во время вызова метода.
Спасибо Нейту Кук, который понял, что reinterpretCast()
может быть использован для лечения UnsafePointer<CChar>
вернулся mkdtemp()
как CString
чтобы его можно было передать stringWithFileSystemRepresentation()
см. Работа со строками C в Swift или: Как преобразовать UnsafePointer
Начиная с Xcode 6 beta 6, reinterpretCast()
больше не требуется, и приведенный выше код может быть упрощен до
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
}