Swift 3.0 FileManager.fileExists(atPath:) always return false

26,315

Solution 1

I assume your url is an URL type. If so try this out:

let filePath = url?.path  // always try to work with URL when accessing Files
if(FileManager.default.fileExists(atPath: filePath!)){  // just use String when you have to check for existence of your file
    let result = NSData(contentsOf: url!)  // use URL instead of String
}

Saying enough, you should change your implementation like this:

if(FileManager.default.fileExists(atPath: (url?.path)!)){  // just use String when you have to check for existence of your file
    let result = NSData(contentsOf: url!)  // use URL instead of String
}

EDIT: 1

There is even more better way, you can call it swift-way (:D). You don't have to explicitly check for file existence.

guard let result = NSData(contentsOf: fileURL) else {
    // No data in your fileURL. So no data is received. Do your task if you got no data
    // Keep in mind that you don't have access to your result here.
    // You can return from here. 
    return
}
// You got your data successfully that was in your fileURL location. Do your task with your result.
// You can have access to your result variable here. You can do further with result constant.
print(result)

Update for Swift 3.0+ without the Objective-Cish NS prefix:

do {
    let result = try Data(contentsOf: fileURL)
    print(result)
} catch {
    print(error)
}

Solution 2

in swift 3 just in case anyone gets confused like i did, here's the full snippets:

let str = "file:///Users/martian2049/Library/Developer/CoreSimulator/Devices/67D744AA-6EEC-4AFD-A840-366F4D78A18C/data/Containers/Data/Application/DD96F423-AF9F-4F4D-B370-94ADE7D6D0A5/Documents/72b8b0fb-7f71-7f31-ac9b-f9cc95dfe90d.mp3"

let url = URL(string: str)
print(url!.path,"\n")

if FileManager.default.fileExists(atPath: url!.path) {
    print("FILE Yes AVAILABLE")
} else {
    print("FILE NOT AVAILABLE")
}

this prints

/Users/martian2049/Library/Developer/CoreSimulator/Devices/67D744AA-6EEC-4AFD-A840-366F4D78A18C/data/Containers/Data/Application/DD96F423-AF9F-4F4D-B370-94ADE7D6D0A5/Documents/72b8b0fb-7f71-7f31-ac9b-f9cc95dfe90d.mp3 

FILE Yes AVAILABLE

notice how the 'file://' got chopped off?

Solution 3

I want to share my experience, in case anyone else gets baffled by this.

Tested on iOS 10-11, Xcode 9.2 and Swift 3.2.

Short answer: if you save a file path to disk, you may solve by not including the Documents directory in it. Instead, every time you need to retrieve the file with the saved path, get the Documents directory and append the path.


For an iOS app, I was saving an image to .../Documents/Pictures through the relative URL, let's say url. As the image was saved, a path, let's say url.path, was saved too in a Core Data entity.

When I later tried retrieving the image through FileManager.default.fileExists(atPath: url.path), it always returned false.

I was testing the app on my iPhone. It turned out that, for some reason, every time I ran the app from Xcode, the app identifier folder changed!!

So:

  • App opened from Xcode -> Image saved -> app closed -> app opened from physical device -> fileExists -> TRUE
  • App opened from Xcode -> Image saved -> app closed -> app opened from Xcode -> fileExists -> FALSE

You can check if this is your case by getting and printing the Document folder path (or URL, it doesn't matter) and comparing it with the saved path (or URL). If you get something like this:

  • /var/mobile/Containers/Data/Application/5D4632AE-C432-4D37-A3F7-ECD05716AD8A/Documents..
  • /var/mobile/Containers/Data/Application/D09904C3-D80D-48EB-ACFB-1E42D878AFA4/Documents..

you found the issue.

Solution 4

Just use path instead of absoluteString to remove file://

FileManager.default.fileExists(atPath: URL.init(string: "your_url")!.path)
Share:
26,315

Related videos on Youtube

Dean Lee
Author by

Dean Lee

Updated on January 04, 2021

Comments

  • Dean Lee
    Dean Lee over 3 years

    When I use method .fileExists(atPath:)to judge whether the file is exist in file system, the method always return false to me. I checked the file system and the file do exist. Here is my code:

    let filePath = url?.path
    var isDir : ObjCBool = false
    if(self.fileManager.fileExists(atPath: filePath!, isDirectory: &isDir)){
         let result = NSData(contentsOfFile: filePath!)
    }
    

    or

    let filePath = url?.path
    if(self.fileManager.fileExists(atPath: filePath!)){
         let result = NSData(contentsOfFile: filePath!)
    }
    

    the if clause will always be skipped.

    • user3608500
      user3608500 about 7 years
      Are you pointing to the exact file location where the file exists??
    • mlidal
      mlidal about 7 years
      What is the value of filePath? Does it start with ~? If so you first need to call expanding​Tilde​In​Path
    • Dean Lee
      Dean Lee about 7 years
      @user3608500 Yes, pointed to a exact file,I wanna judge this file is existed.
    • Dean Lee
      Dean Lee about 7 years
      @mlidal start with "/Users/De...."
    • Muhammad Raza
      Muhammad Raza about 7 years
      maybe path is not correct? please check url
    • Bob
      Bob about 7 years
      How are you obtaining self.fileManager? It could be that the issue is related to that somehow.
  • Dean Lee
    Dean Lee about 7 years
    1.Path is "/Users/De/Library/Developer/CoreSimulator/Devices/~~~/Docum‌​ents/Cache/qbyNPuA.m‌​p3" , 2.this file is written by code so I think it is accessible .
  • Tom Roggero
    Tom Roggero almost 7 years
    GREAT! In my case i was using .absoluteString instead of .path. This fixed it
  • MartianMartian
    MartianMartian over 6 years
    honestly, if i can go back, i would have learned OC instead. swift is hardly a common language
  • ixany
    ixany about 6 years
    pointing out that file:// got chopped off was essential. thank you so much.
  • IvanMih
    IvanMih over 5 years
    That was the right explanation for me. Perhaps add some code for saving and retrieving images for others seeking help.
  • Joel
    Joel over 5 years
    Using .path was the key for me, instead of .absoluteString.
  • Alex Suzuki
    Alex Suzuki over 5 years
    This solved my problem. What can be extra confusing is when you download the container and you see that file is there.
  • cbiggin
    cbiggin almost 5 years
    This should be the accepted answer here. Most of the other answers are duplicates of stackoverflow.com/questions/34135305/…
  • Nezih Yılmaz
    Nezih Yılmaz over 4 years
    This was the case for me. Thank you.
  • Stefan Vasiljevic
    Stefan Vasiljevic about 2 years
    Fing GOLD man. Thx a ton. I was starting to go crazy :)