This question already has answers here:
NSFileManager.defaultManager().fileExistsAtPath returns false instead of true
(2 answers)
Closed 4 years ago.
FileManager.default.contentsOfDirectory claims that the documents directory does not exist, even though it clearly does. I'm using Swift 4.2 on my actual iPhone SE running iOS 12.1.2
I am reading the contents of the downloads directory in my app using the following:
do {
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let downloadedContents = try FileManager.default.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil)
print(downloadedContents)
} catch {
print("Error while enumerating contents: \(error.localizedDescription)")
}
This prints the following, telling me that a file exists in the documents directory:
[file:///private/var/mobile/Containers/Data/Application/698F8D51-92AF-4BAB-A212-0A0982090550/Documents/example-file/]
(I moved the file there from the caches directory after downloading an in-app purchase, but I don't think that's relevant to this question).
Later in my code, I want to check if the file was downloaded. I'm using the following:
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let path = URL(fileURLWithPath: "example-file", relativeTo: documentsURL)
var isDir : ObjCBool = false
if FileManager.default.fileExists(atPath: path.standardizedFileURL.absoluteString, isDirectory: &isDir) {
if isDir.boolValue {
return true
} else {
return false // file exists but is not directory
}
} else {
return false // file does not exist at all
}
But this always returns false, even though contentsOfDirectory showed it exists.
While debugging, I also tried:
let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
po FileManager.default.fileExists(atPath: documentsURL.standardizedFileURL.absoluteString)
But this, too, returns false. Now I'm pretty sure I'm just using the fileExists methods incorrectly.
Can anyone spot what I'm doing wrong?
Turns out one should use documentsURL.path, instead of any sort of URL.
The path begins with /var/mobile... whereas the URLs begin with file:///var...
Related
I'm trying to write a file locally but no success. When I try to get the user's document directory it returns nil and I believe this is why my file is not been stored.
Also, I have many doubts of what the "user's document directory" is supposed to mean. Is it the "Documents/" inside "iCloud Drive" or "on my phone". Should I be looking in another place instead of "Files" app? I'm using the iPhone simulator.
My code is designed as follow. documentFolderURL, fileURL and url are all nil when debugging.
let documentFolderURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
let ext: String = type ?? "pdf"
let name = "extrato." + ext
let fileURL = documentFolderURL?.appendingPathComponent(name)
do {
if let url = fileURL {
try file.write(to: url, options: .atomic)
}
} catch {...}
Use the throwing API to get an error (there should be none)
do {
let documentFolderURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let ext: String = type ?? "pdf"
let fileURL = documentFolderURL.appendingPathComponent(name).appendingPathExtension(ext)
try file.write(to: fileURL, options: .atomic)
} catch { print(error) }
It seems that you are creating the file successfully, but you aren't looking for it in the right place.
You can navigate to the simulator's User Defaults folder by:
Print the file path of the simulator's documents directory. print(documentFolderURL) should print something like file:///Users/yourname/Library/Developer/CoreSimulator/Devices/8DAF542C-4B37-41D1-BA43-1D7C2A32E585/data/Containers/Data/Application/63545C94-56F5-3B11-B601-543801BE717A/Documents/
Copy the entire url EXCEPT the leading file:// (in other words, start with /User/yourname...
Open your macbook's Finder app, and press command + shift + g. This will allow you to...(drum roll please)...
Paste in the url to navigate to your simulator's documents directory.
Your file should be there :)
I wrote a file in .documentDirectory in .userDomainMask:
do {
let fileManager = FileManager.default
let docs = try fileManager.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil, create: false)
let path = docs.appendingPathComponent("myName.txt")
let data = "Hai...!".data(using: .utf8)!
fileManager.createFile(atPath: path.absoluteString, contents: data, attributes: nil)
} catch {
// handle error
}
I have not gotten any errors or exceptions. It runs perfectly. But I can't see that file. Where can I find that file?
just add in target -> info -> custom iOS Target properties
Application supports iTunes file sharing - YES
and you will be able to see the folder you saved a file in Files app on your simulator.
Otherwise use print(FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)) to get a path to folder using Finder
This question already has an answer here:
UIImage(contentsOfFile:) returning nil despite file existing in caches directory [duplicate]
(1 answer)
Closed 4 years ago.
I have the following swift function that I hoped would save incoming bytes to a JPEG file on iOS. Unfortunately an exception is thrown by the call to data.write and I get the error message
The folder “studioframe0.jpg” doesn’t exist. writing to file:/var/mobile/Containers/Data/Application/2A504F84-E8B7-42F8-B8C3-3D0A53C1E11A/Documents/studioframe0.jpg -- file:///
Why does iOS think it is a directory path to a directory which does not exist as opposed to a file that I am asking it to write?
func saveToFile(data: Data){
if savedImageCount < 10 {
guard let documentDirectoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return
}
let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("studioframe\(savedImageCount).jpg").absoluteString)
savedImageCount += 1
do {
try data.write(to: imgPath, options: .atomic)
print("Saved \(imgPath) to disk")
} catch let error {
print("\(error.localizedDescription) writing to \(imgPath)")
}
}
}
URL(fileURLWithPath together with absoluteString is wrong.
You would have to write (note the different URL initializer):
let imgPath = URL(string: documentDirectoryPath.appendingPathComponent("studioframe\(savedImageCount).jpg").absoluteString)
but this (URL → String → URL) is very cumbersome, there is a much simpler solution, please consider the difference between (string) path and URL
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! // the Documents directory is guaranteed to exist.
let imgURL = documentDirectoryURL.appendingPathComponent("studioframe\(savedImageCount).jpg")
...
try data.write(to: imgURL, options: .atomic)
I created a file in the document directory and for some reason when I try to delete it using the code below, it doesn't get deleted. The code doesn't throw any errors, but the file is still there
let fileManager = FileManager.default
if let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
let filePath = documentDirectory.appendingPathComponent("data.json")
do {
try fileManager.removeItem(atPath: filePath.path)
} catch let error as NSError {
print(error.localizedDescription)
}
}
I also tried to put it inside another folder and remove the folder but still the same problem.
This is the path where the file is stored :
Users/user1/Library/Developer/CoreSimulator/Devices/76AFDB69-75C8-464E-93F2-6ABF622068FD/data/Containers/Data/Application/7D268156-977A-4A3C-834B-6B13FA3DE76D/Documents/
you can try like below
if let filePath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("data.json"), fileManager.fileExists(atPath: filePath.path) {
do {
try fileManager.removeItem(atPath: filePath.path)
} catch let error as NSError {
print(error.localizedDescription)
}
}
The code doesn't throw any errors, but the file is still there
No, it isn't. The problem is with the way you are checking to see whether "the file is still there". You are looking on your computer for the file. But iOS files are sandboxed. At the time you are looking, the path where the file was is completely different from your claimed path:
Users/user1/Library/Developer/CoreSimulator/Devices/76AFDB69-75C8-464E-93F2-6ABF622068FD/data/Containers/Data/Application/7D268156-977A-4A3C-834B-6B13FA3DE76D/Documents/
Such paths are not permanent. They are meaningless and should not be used. The only way to know whether the file is still there is with more code from inside iOS, i.e. ask the FileManager. When you do, you will find that you are, indeed, deleting the file successfully.
This question already has answers here:
Objc save a file to the tmp/ with URL it is not working
(1 answer)
UIImage(contentsOfFile:) returning nil despite file existing in caches directory [duplicate]
(1 answer)
NSURL path vs absoluteString
(3 answers)
Closed 5 years ago.
I'm trying to remove a file from the documents directory using FileManager.default.removeItem but is not deleting the file on the simulator. Here is my code:
if let dir = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
do {
let path = dir.appendingPathComponent(file).absoluteString
do {
try FileManager.default.removeItem(atPath:path)
} catch {
print(error)
}
}
}
But I always fails. Any of you knows why it fails?
You can write like this:
var filemanager = FileManager.default
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true)[0] as NSString
let destinationPath = documentsPath.appendingPathComponent("Filename.jpg")
try! filemanager.removeItem(atPath: destinationPath)
absoluteString is the wrong API, the correct property for the file:// scheme is path.
The best solution is to use the URL related API
let fileURL = dir.appendingPathComponent(file)
...
try FileManager.default.removeItem(at: fileURL)