【问题标题】:How to retrieve nested file with FileManager?如何使用 FileManager 检索嵌套文件?
【发布时间】:2017-05-30 01:57:12
【问题描述】:

在我的应用程序中,我会在应用程序首次启动时创建此文件夹结构:

我在这里读到Can I save the keep the absolute path of a file in database? - 我不应该存储目录或文件的绝对路径。 因此,我无法引用上图中显示的最后一个名为 I-Want-This-File-Path的文件。

我可以像这样访问上图中的Feed 文件夹:

extension FileManager {
    /// APPLICATION SUPPORT DIRECTORY
    static func createOrFindApplicationSupportDirectory() -> URL? {
        let bundleID = Bundle.main.bundleIdentifier
        // Find the application support directory in the home directory.
        let appSupportDir = self.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)

        guard appSupportDir.count > 0 else {
            return nil
        }

        // Append the bundle ID to the URL for the Application Support directory.
        let dirPath = appSupportDir[0].appendingPathComponent(bundleID!)

        // If the directory does not exist, this method creates it.
        do {
            try self.default.createDirectory(at: dirPath, withIntermediateDirectories: true, attributes: nil)
            return dirPath
        } catch let error {
            print("Error creating Application Support directory with error: \(error)")
            return nil
        }
    }

    /// FEED DIRECTORY
    static func createOrFindFeedDirectory() -> URL? {
        guard let appSupportDir = createOrFindApplicationSupportDirectory() else {
            return nil
        }

        let dirPath = appSupportDir.appendingPathComponent("Feed")

        // If the directory does not exist, this method creates it.
        do {
            try self.default.createDirectory(at: dirPath, withIntermediateDirectories: true, attributes: nil)
            return dirPath
        } catch let error {
            print("Error creating Favorites directory with error: \(error)")
            return nil
        }
    }
}

要访问FileStack 文件夹,我有一个名为FileStack 的对象,它保存了path 的一部分。我没有保存绝对路径,而是像这样在运行时构建它:

class FileStack {

    var title = ""
    var localDirectoryName: String?
    var files: File? // THIS OBJECT IS WHERE I WANT TO SAVE THE PATH

    // THIS IS HOW I BUILD THE URL AT RUNTIME TO GET THE PATH TO THE DIRECTORY CALLED "FILESTACK"
    var localDirectoryPath: URL? {
        guard let localDirectoryName = localDirectoryName else { return nil }
        return FileManager.createOrFindFeedDirectory()?.appendingPathComponent(localDirectoryName)
    }
}

注意属性var files: File?- 这是一个名为File 的自定义对象,我想在其中保存上图中I-Want-This-File-Path 文件的路径。对象是这样的:

class File {

    dynamic var iWantThisFileName: String?

    var iWantThisFilePath: URL? {
        guard let iWantThisFileName = iWantThisFileName else { return nil }
        return /// ??? HOW DO I RETURN THE PATH HERE?
    }
}

所以最终我希望能够获得I-Want-This-File-Path的路径就像这样

let fileStack = FileStack()
fileStack.file.iWantThisFilePath // This will give me the path

有什么建议吗?

更新 1

在Application Support -> com.Company.DemoApp 目录下,会有多个文件夹。例如,此处显示的 Feed 和 SavedForLater。 FileStack 也会有多个文件,如下所示。

更新 2

换句话说,我无法在运行时为 File 对象构建路径。

我需要将FileStacklocalDirectoryName 传递给它的嵌套对象File,因为File 对象将需要它来在运行时构建它的路径。我有上面的代码,它显示了这样的内容。 如果这些是单独的对象,意味着不相互嵌套,我可以简单地将url 传递给下一个对象......但由于它们是嵌套的,我被卡住了。


【问题讨论】:

    标签: ios objective-c swift nsurl nsfilemanager


    【解决方案1】:

    我认为您误解了其他问题的答案。 你想得到这个路径:

    /Library/Application Support/com.Company.DemoApp/Feed/FileStack/I-Want-This-File
    

    /Library/Application Support/ 这是您无法保存在任何地方的部分,您必须在运行时从 FileManager 获取它。这是因为您无法控制此路径,并且可以在未经您批准的情况下更改。您希望应用程序中的路径与此文件夹相关。

    com.Company.DemoApp/Feed/FileStack/I-Want-This-File 这是您可以存储在数据库/配置文件中的文件路径的一部分。只有当你改变它时,这条路径才会改变。因此,如果您更新应用程序并更改路径,您也可以更改数据库中的路径。

    这是如何实现的粗略示例:

    enum DataDirectoryType : String
        {
        case wantedFile = "Feed/FileStack/I-Want-This-File-Path"
        case anotherFiles = "Feed/AnotherFiles/"
    }
    
    extension FileManager {
        /// APPLICATION SUPPORT DIRECTORY
        static private func createOrFindApplicationSupportDirectory() -> URL? {
            let bundleID = Bundle.main.bundleIdentifier
            // Find the application support directory in the home directory.
            let appSupportDir = self.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    
            guard appSupportDir.count > 0 else {
                return nil
            }
    
            // Append the bundle ID to the URL for the Application Support directory.
            return appSupportDir[0].appendingPathComponent(bundleID!)
        }
    
        static func createOrFindFilePath(_ type : DataDirectoryType ) -> URL? {
            guard let appSupportDir = createOrFindApplicationSupportDirectory() else {
                return nil
            }
    
            let dirPath = appSupportDir.appendingPathComponent(type.rawValue)
    
            // If the directory does not exist, this method creates it.
            do {
                try self.default.createDirectory(at: dirPath, withIntermediateDirectories: true, attributes: nil)
                return dirPath
            } catch let error {
                print("Error creating Favorites directory with error: \(error)")
                return nil
            }
        }
    }
    
    
    let urlToWantedFile = FileManager.createOrFindFilePath(.wantedFile)
    

    【讨论】:

    • 太棒了!跟进问题:我正在使用Alamofire 使用Alamofire.download 函数下载文件。 Alamofire 有一个destinationURL 属性,它告诉您文件在文件系统中的下载位置。我目前正在做的是保存destinationURL.lastPathComponent,这只是我模型对象中属性的文件名。在这种情况下,我将其保存到 iWantThisFileName。然后,当我想检索它时,我使用 iWantThisFilePath 在运行时构建路径。这就是你要完成的方法吗?
    • 使用Alamofire 下载后获得Feed/FileStack/I-Want-This-File-Path 之类的内容会很好。但我能得到的最好的是destinationURL.lastPathComponent,它只给了我I-Want-This-File-Path这个名字(因此我必须再次构建路径)
    • 你可以告诉 Alamofire 在哪里下载文件。所以你不需要存储 Alamofire 生成的任何路径。 github.com/Alamofire/Alamofire#download-file-destination
    • 是的,我看到了,再次感谢您的澄清!很棒的答案!
    • 我发布了一个后续问题,你能看一下吗?那将不胜感激! :) 这是链接:stackoverflow.com/questions/41729519/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 2013-07-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多