问题
In my app, I create this folder structure as soon as the app launches for the first time:
I read here Can I save the keep the absolute path of a file in database? - that I should not store the absolute path to a directory or file. Therefore I am having trouble getting reference to the last file shown in the picture above called I-Want-This-File-Path
.
I could get access up to the Feed
folder in the picture above like so:
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
}
}
}
To get access to the FileStack
folder I have an object called FileStack
which saves part of the path
. Instead of saving the absolute path, I build it at runtime like so:
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)
}
}
Notice the property var files: File?
- this is a custom object called File
where I want to save the path to I-Want-This-File-Path
file in the picture above. THe object is like so:
class File {
dynamic var iWantThisFileName: String?
var iWantThisFilePath: URL? {
guard let iWantThisFileName = iWantThisFileName else { return nil }
return /// ??? HOW DO I RETURN THE PATH HERE?
}
}
So ultimately I want to be able to get the path of I-Want-This-File-Path
like so:
let fileStack = FileStack()
fileStack.file.iWantThisFilePath // This will give me the path
Any suggestions?
Update 1
In the Application Support -> com.Company.DemoApp directory, there will be multiple folders. For example, a Feed and SavedForLater as shown here. Also FileStack will have multiple files as shown here.
Update 2
In other words, I am having trouble building out the path for the File
object at runtime.
I need to pass the FileStack
's localDirectoryName
to it's nested object File
because the File
object will need that to build out it's path at runtime. I have the code above which shows something like this.
If these were separate objects, meaning not nested within each other, I could simply pass a url
to the next object... but since they are nested, I'm stuck.
回答1:
I think that you misunderstood the answer in other question. You want to get this path:
/Library/Application Support/com.Company.DemoApp/Feed/FileStack/I-Want-This-File
/Library/Application Support/
this is the part you can't save anywhere and you have to get it during runtime from FileManager. This is because you have no control over this path and it can change without your approval. You want paths in your application to be relative to this folder.
com.Company.DemoApp/Feed/FileStack/I-Want-This-File
this is part of that file path that you can store in database/config files. This path will change only when you change it. So If you update your application and change paths you can also change paths in database.
This is rough example how it can be implemented:
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)
来源:https://stackoverflow.com/questions/41655887/how-to-retrieve-nested-file-with-filemanager