【问题标题】:Document directory path change when rebuild application重建应用程序时更改文档目录路径
【发布时间】:2018-05-31 12:58:57
【问题描述】:

我从 url 下载视频文件,并用这个路径保存在文档目录中:

  let destination: DownloadRequest.DownloadFileDestination = { _, _ in
      let pathComponent = "pack\(self.packID)-\(selectRow + 1).mp4"
      let directoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
      let folderPath: URL = directoryURL.appendingPathComponent("Downloads", isDirectory: true)
      let fileURL: URL = folderPath.appendingPathComponent(pathComponent)
      return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
    }

我的视频已下载并成功播放。 但是有一个问题,当我在 Xcode 中重建应用程序并尝试播放我下载的最后一个视频时,视频没有显示,当我下载一个新视频时,这个保存并成功播放。

我看过每个视频包的路径,它们是不同的。

1 - file:///Users/myMac/Library/Developer/CoreSimulator/Devices/EAC2F4CE-EA09-46C0-B403-1CE9E24B6822/data/Containers/Data/Application/1D2C1F7B-E627 -4898-91C1-D0AF8D5E0F1E/Documents/Downloads/pack7-1.mp4

2 - file:///Users/myMac/Library/Developer/CoreSimulator/Devices/EAC2F4CE-EA09-46C0-B403-1CE9E24B6822/data/Containers/Data/Application/F950E9A5-C9F3-4B8C-BCF5 -647EEC233CEE/Documents/Downloads/pack7-3.mp4

现在,我的问题是,当我们从 App Store 更新应用时,是否意味着重新安装?这个路径会改变吗?

如何解决这个问题?

【问题讨论】:

  • @ivarun:不正确!从 iOS 8 开始,每次应用启动时应用的绝对 URL 都会发生变化,看看 stackoverflow.com/questions/26988024/…
  • @ava:你检查我发布的答案了吗?那没有帮助吗?还有什么问题吗?
  • @SandeepBhandari 是的,我所做的与您在我们的答案中显示的相同,但在检索文件时未找到错误即将到来。

标签: ios swift filepath nsdocumentdirectory


【解决方案1】:

从 iOS 8 开始,每次重新启动应用程序时,应用程序沙箱的绝对 URL 都会更改。因此,您永远不应该保存视频的绝对网址。每次重新启动应用时保存视频名称并重新创建 url。

  let pathComponent = "pack\(self.packID)-\(selectRow + 1).mp4"
  let directoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
  let folderPath: URL = directoryURL.appendingPathComponent("Downloads", isDirectory: true)
  let fileURL: URL = folderPath.appendingPathComponent(pathComponent)

拥有fileURL 后,查找文件,您将找到在之前启动时下载的文件。

每次用户启动应用时,iOS 都会为应用创建一个新的沙盒。因此绝对 URL 会非常。但 iOS 会像以前一样负责设置沙盒内的所有文件夹和内容。因此,尽管 SandBox 的基本 url 发生变化,但所有内容的相对 url 将保持不变。

因此建议永远不要将绝对网址保存到任何文件夹:) 希望对您有所帮助

【讨论】:

  • 有人可以访问文档目录下的这个文件夹并复制这个文件夹的内容吗?
  • @ava :如果有人可以访问 iPhone,那么是的 :) 您可以随时将 iPhone 连接到 Mac 并使用第三方应用程序打开应用程序沙箱并复制内容。如果您想保护文件免受此类访问,有多种解决方案
  • @ava :解决方案 1:将文件保存在临时文件夹中。保存在临时文件夹中的所有内容都不受 iCloud 支持,也没有应用程序可以访问它们。但一个问题是临时文件夹中的内容没有持久化。当应用程序被杀死时,临时文件夹中的所有内容都将丢失:D 因此名称为 temp。阅读:developer.apple.com/library/content/documentation/…
  • 哦,我正在使用Alamofire下载方法,我应该找到这个视频下载不保存为mp4文件的解决方案。感谢您的回复。
  • @ava : 等一下,我还有两个文件安全解决方案 :) 然后打电话
【解决方案2】:

我建议使用书签。 查看以下文章中的使用书签定位文件部分:https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html#//apple_ref/doc/uid/TP40010672-CH3

编辑:

链接文档的一些相关部分,以防万一:

重要提示:虽然它们在您的应用运行时可以安全使用, 文件引用 URL 在启动之间存储和重用是不安全的 你的应用程序,因为如果系统重新启动,文件的 ID 可能会更改。 如果您想在之间永久存储文件的位置 启动您的应用程序,创建一个书签,如定位文件中所述 使用书签。

我有一个使用大量文件处理的应用程序,因此我在 NSURL 类别中创建了以下方法来返回给定 URL 的书签数据。

- (NSData*)defaultBookmark
{
    NSError* error = nil;
    NSData* bookmarkData =  [self bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile
                           includingResourceValuesForKeys:nil
                                            relativeToURL:nil
                                                    error:&error];
    if (error != nil)
    {
        NSLog(@"error creating bookmark for url '%@': %@", self, error);
    }
    return bookmarkData;
}

要从书签数据创建一个 NSURL 对象,请使用类似:

    NSError* error = nil;
    BOOL isStale = NO;
    NSURL* url = [NSURL URLByResolvingBookmarkData:bookmarkData
                                           options:NSURLBookmarkResolutionWithoutUI
                                     relativeToURL:nil
                               bookmarkDataIsStale:&isStale
                                             error:&error];
    if (error != nil || url == nil)
    {
        NSLog(@"Error restoring url from bookmark: %@", error);
    }
    else
    {
        // use url to load file
        ...
    }

【讨论】:

  • 我认为这是最好的解决方案。
【解决方案3】:

关于接受的答案尚不清楚的一点是,当您想从 Document 的目录中获取文件时,您实际上是如何搜索文件。我们开始:

保存文件(例如图像):

func saveImage(with imageName: String) {
    guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {return}
    guard let data = image.jpegData(compressionQuality: 1) else {return}
    let url = documentsDirectory.appendingPathComponent(imageName)
    do {
        try data.write(to: url)
    } catch {
        print("Error saving image")
    }
    
}

获取文件:

func fetchImage(with imageName: String) -> UIImage? {
    let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
    if let path = paths.first {
        let imageURL = URL(fileURLWithPath: path).appendingPathComponent(imageName)
        let data = try! Data(contentsOf: imageURL)
        if let image = UIImage(data: data) {
            return image
        }
    }
    return nil
}

再说一次:我们的想法不是保存文件的完整路径,因为当您尝试从该路径重新启动后获取文件时,将无法正常工作。您应该做的是保存文件的名称(上例中的 imageName)。然后搜索具有该名称的文件。

【讨论】:

    猜你喜欢
    • 2015-10-23
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    相关资源
    最近更新 更多