【问题标题】:Accessing temp directory in Swift在 Swift 中访问临时目录
【发布时间】:2014-06-18 09:03:04
【问题描述】:

我试图在 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>。有没有我应该查看的文件?

谢谢。

【问题讨论】:

    标签: objective-c macos cocoa swift


    【解决方案1】:

    像这样的东西怎么样:

    public extension FileManager {
        func createTempDirectory() throws -> String {
            let tempDirectory = (NSTemporaryDirectory() as NSString).appendingPathComponent(UUID().uuidString)
            try FileManager.default.createDirectory(atPath: tempDirectory,
                                                    withIntermediateDirectories: true,
                                                    attributes: nil)
            return tempDirectory
        }
    }
    

    它没有回答您关于 char* 的问题,但它更简洁......

    NSFileManager 参考 here.

    还可以查看 this SO question 了解唯一名称。

    【讨论】:

    • 请注意,BSD 函数 mkdtemp() 与 NSFileManager createDirectoryAtPath 方法不同,因为它根据给定的模板创建一个唯一的目录名称
    • @Grimxn 谢谢!我稍后会尝试。顺便说一句,createDirectoryAtPath(path: String!, attributes: NSDictionary!) 似乎已被弃用,现在是createDirectoryAtURL:withIntermediateDirectories:attributes:error:。这是否意味着我可以使用createFileAtPath() 以相同的方法创建一个临时文件?
    • @MartinR 所以如果我使用 createDirectoryAtPath,我需要创建我的唯一名称?
    • 查看我添加到答案中的 SO 链接 - 他们处理创建唯一名称。
    • 你不应该使用错误作为指针。您应该使用 var error: NSError 并使用与号来获取地址,这样您就可以使用错误。你如何取消引用 NSErrorPointer?
    【解决方案2】:

    根据 Apple 的说法,不鼓励使用 NSTemporaryDirectory

    查看 FileManager 方法 url(for:in:appropriateFor:create:) 查找正确临时目录的首选方法。更多 有关临时文件的信息,请参阅文件系统编程指南。

    因此,您应该使用FileManager.default.temporaryDirectory

    或者如果你想要一个唯一的路径:

    let extractionPath = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
    
    

    【讨论】:

      【解决方案3】:

      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
      }
      

      【讨论】:

        【解决方案4】:

        Swift 3 及更高版本

        我认为快速执行此操作的一个好方法是使用 FileManager 上的扩展名。这应该会创建一个唯一的临时文件夹并将 URL 返回给您。

        extension FileManager{
        
            func createTemporaryDirectory() throws -> URL {
                let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString)
        
                try createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
                return url
            }
        }
        

        【讨论】:

          【解决方案5】:

          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
          }
          

          【讨论】:

          • 其他想要使用它的人的一些事情:1>您已经创建了一个带有文件扩展名的 URL,并且正在创建一个文件夹,并且 2>,如果这将返回 nil目录已经存在,这可能是您(和原始海报)想要的行为,但在大多数情况下,即使目录已经存在,用户也可能想要结果。 (这两件事都未经测试,但除非 Swift 的行为与 Obj-C 不同,否则这是我所期望的结果)
          【解决方案6】:

          将您的 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 方法。该方法创建 模板中的目录名称,保证在该时间不存在 该方法被调用。

          感谢 Nate Cook,他发现reinterpretCast() 可用于将mkdtemp() 返回的UnsafePointer&lt;CChar&gt; 视为CString,以便将其传递给stringWithFileSystemRepresentation(),参见Working with C strings in Swift, or: How to convert UnsafePointer<CChar> to CString


          从 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
          }
          

          【讨论】:

            猜你喜欢
            • 2010-10-07
            • 1970-01-01
            • 1970-01-01
            • 2011-12-01
            • 1970-01-01
            • 2022-08-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多