【问题标题】:Inconsistent directories in SwiftSwift 中的目录不一致
【发布时间】:2021-07-18 17:36:33
【问题描述】:

我有以下代码来获取目录并创建可以保存视频的路径:

func getOutputDirectory() -> String {
    let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory,
                                                                .userDomainMask,
                                                                true)
    return documentDirectory[0]
}

func append(toPath path: String, withPathComponent pathComponent: String) -> String? {
    if var pathURL = URL(string: path) {
        pathURL.appendPathComponent(pathComponent)
        return pathURL.absoluteString
    }
    return nil
}

当我想加载包含录制视频的列表时,我会调用:

func getListOfMovies() -> [String] {
    do {
        let dir = getOutputDirectory()
        let files = try FileManager().contentsOfDirectory(atPath: dir)
        var paths: [String] = []
        for file in files {
            paths.append(append(toPath: dir, withPathComponent: file)!)
        }
        return paths
    }
    catch {
            print("Could not load files")
    }
    return []
}

奇怪的是,每次我加载列表时,我都会得到不同的路径,当我尝试播放视频时它没有显示。

以下是具有两个不同路径的同一文件的示例:

file:///var/mobile/Containers/Data/Application/622EE247-1695-4E40-B261-50A310F45ADB/Documents/18%252520Jul%2525202021%252520at%25252017:28:00.mov

file:///var/mobile/Containers/Data/Application/F28FBA1C-952F-4BD6-BFCA-9C5DEE8C1478/Documents/18%252520Jul%2525202021%252520at%25252017:28:00.mov

要播放视频,我有以下View

struct PlayVideo: View {
    var moviePath: URL?
    
    init(filePath: String) {
        moviePath = getURL(path: filePath)
    }
    var body: some View {
        VideoPlayer(player: AVPlayer(url: moviePath!))
            .frame(height: 400)
    }
}

func getURL(path: String) -> URL? {
    return URL(fileURLWithPath: path)
}

按照 vadian 的以下建议,将 getListOfMovies() 更改为

func getListOfMovies() -> [String] {
    do {
        let files = try FileManager.default.contentsOfDirectory(at: documentDirectoryURL(), includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
        var names: [String] = []
        for file in files {
            names.append(file.lastPathComponent)
        }
        return names
    }
    catch {
        print("Unexpected error loading files: \(error).")
    }
    return []
}

终于成功了。

【问题讨论】:

    标签: swift avplayer


    【解决方案1】:

    这种行为是正常的,并且是有意的。容器的名称会定期更改。始终只保存结构中的文件名,并在您要加载文件时获取到 Documents 文件夹的实际 URL

    但代码中有一个致命错误,URL(string:) 是从文件系统路径创建 URL 的错误 API。你必须使用URL(fileURLWithPath:)

    不过我建议重构代码以使用与 URL 相关的 API

    func documentDirectoryURL() -> URL {
        return try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    }
    
    func fileURL(for filename: String) -> URL {
        return documentDirectoryURL().appendingPathComponent(filename)
    }
    

    【讨论】:

    • 谢谢,但我正在使用func getURL(path: String) -> URL? { return URL(fileURLWithPath: path) }
    • 是的,但是在getListOfMovies() 中,您使用的是append(toPath,它返回了无效的 URL。正如我在答案中所说,您根本不应该使用字符串路径 API,因为它很容易出错。顺便说一句,URL(fileURLWithPath 总是返回一个非可选的。
    • 谢谢,我会进行重构。希望有效!
    • 它现在可以工作,但我需要更改为let files = try FileManager.default.contentsOfDirectory(at: documentDirectoryURL(), includingPropertiesForKeys: nil, options: .skipsHiddenFiles) var names: [String] = [] for file in files { names.append(file.lastPathComponent) } 当我使用 atPath 时,它抛出了一个关于目录不存在的异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 2017-10-26
    • 2016-02-03
    • 1970-01-01
    相关资源
    最近更新 更多