Swift 3.0
FileManager
fileExists(atPath:)
debugging
programming error

Swift 3.0 FileManager.fileExistsatPath always return false

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

When FileManager.default.fileExists(atPath:) always returns false, the most common cause is passing a URL object (or URL string with file:// prefix) instead of a plain file path string. fileExists(atPath:) expects a POSIX path like /Users/name/file.txt, not a URL like file:///Users/name/file.txt. Other causes include sandbox restrictions (iOS apps can only access their own containers), incorrect bundle resource paths, and case sensitivity on certain file systems.

The Most Common Cause: URL vs Path

swift
1let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
2let fileURL = documentsURL.appendingPathComponent("data.json")
3
4// WRONG: passing a URL description as the path
5let exists = FileManager.default.fileExists(atPath: fileURL.absoluteString)
6// "file:///var/mobile/.../data.json" — contains "file://" prefix → false
7
8// CORRECT: use .path to get the POSIX path
9let exists = FileManager.default.fileExists(atPath: fileURL.path)
10// "/var/mobile/.../data.json" — correct path → true (if file exists)

The difference:

  • fileURL.absoluteString"file:///var/mobile/Containers/.../data.json" (URL)
  • fileURL.path"/var/mobile/Containers/.../data.json" (path)

Checking Bundle Resources

swift
1// WRONG: constructing path manually
2let path = "MyApp.app/Resources/config.json"
3FileManager.default.fileExists(atPath: path)  // false
4
5// CORRECT: use Bundle to get the full path
6if let path = Bundle.main.path(forResource: "config", ofType: "json") {
7    let exists = FileManager.default.fileExists(atPath: path)
8    print("Exists: \(exists)")  // true
9} else {
10    print("Resource not found in bundle")
11}
12
13// Or use URL
14if let url = Bundle.main.url(forResource: "config", withExtension: "json") {
15    let exists = FileManager.default.fileExists(atPath: url.path)
16    print("Exists: \(exists)")
17}

iOS Sandbox: Correct Directories

iOS apps can only access their own sandbox directories:

swift
1// Document directory (user data, backed up)
2let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
3
4// Caches directory (temporary data, not backed up)
5let caches = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
6
7// Temporary directory
8let tmp = FileManager.default.temporaryDirectory
9
10// Check a file in documents
11let filePath = docs.appendingPathComponent("user_data.json").path
12if FileManager.default.fileExists(atPath: filePath) {
13    print("File found")
14} else {
15    print("File not found at: \(filePath)")
16}

Debugging File Existence

swift
1func debugFileExists(at path: String) {
2    let fm = FileManager.default
3
4    print("Checking path: \(path)")
5    print("Path contains 'file://': \(path.contains("file://"))")
6    print("File exists: \(fm.fileExists(atPath: path))")
7
8    // Check parent directory
9    let parent = (path as NSString).deletingLastPathComponent
10    print("Parent exists: \(fm.fileExists(atPath: parent))")
11
12    // List parent directory contents
13    if let contents = try? fm.contentsOfDirectory(atPath: parent) {
14        print("Parent contents: \(contents)")
15    }
16
17    // Check if it's a directory
18    var isDir: ObjCBool = false
19    let exists = fm.fileExists(atPath: path, isDirectory: &isDir)
20    print("Exists: \(exists), Is directory: \(isDir.boolValue)")
21}

Writing Then Reading a File

swift
1let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
2let fileURL = docs.appendingPathComponent("test.txt")
3
4// Write
5try "Hello, World!".write(to: fileURL, atomically: true, encoding: .utf8)
6
7// Verify it was written
8let exists = FileManager.default.fileExists(atPath: fileURL.path)
9print("Written and exists: \(exists)")  // true
10
11// Read back
12let content = try String(contentsOf: fileURL, encoding: .utf8)
13print(content)  // "Hello, World!"

macOS: Permissions and Sandboxing

swift
1// macOS sandbox restricts access to user-selected files only
2// Use NSOpenPanel to get permission
3let panel = NSOpenPanel()
4panel.canChooseFiles = true
5panel.begin { response in
6    if response == .OK, let url = panel.url {
7        // Now you have permission to access this path
8        let exists = FileManager.default.fileExists(atPath: url.path)
9        print("Selected file exists: \(exists)")
10    }
11}

Using URL-Based APIs Instead

Modern Swift APIs prefer URLs over paths:

swift
1let fileURL = docs.appendingPathComponent("data.json")
2
3// Check existence using URL (avoids path confusion)
4let exists = (try? fileURL.checkResourceIsReachable()) ?? false
5
6// Or use ResourceValues
7let values = try fileURL.resourceValues(forKeys: [.isRegularFileKey])
8if values.isRegularFile == true {
9    print("It's a regular file")
10}

Common Pitfalls

  • Using url.absoluteString instead of url.path: absoluteString includes the file:// scheme prefix, which fileExists(atPath:) does not understand. Always use .path to get a plain POSIX path from a URL.
  • Hardcoding file paths on iOS: iOS app container paths change between installs and simulator runs. Never hardcode paths like /var/mobile/Containers/.... Always construct paths dynamically using FileManager.urls(for:in:).
  • Checking for a bundle resource that was not added to the target: If a file is in the project navigator but not in the target's "Copy Bundle Resources" build phase, it is not included in the app bundle. Verify the file is listed under Build Phases in Xcode.
  • Testing on the simulator with a case-insensitive file system: macOS (the simulator's host) uses a case-insensitive file system by default, so "Data.json" and "data.json" both resolve. On a real device, the file system is case-sensitive, and mismatched casing returns false.
  • Not handling the isDirectory parameter: fileExists(atPath:) returns true for both files and directories. If you specifically need a file (not a directory), use fileExists(atPath:isDirectory:) and check the ObjCBool output parameter.

Summary

  • Use url.path (not url.absoluteString) when passing a URL to fileExists(atPath:)
  • Use Bundle.main.path(forResource:ofType:) to locate bundle resources
  • Build paths dynamically with FileManager.urls(for:in:) — never hardcode iOS paths
  • Debug by printing the full path and listing the parent directory contents
  • Prefer URL-based APIs (checkResourceIsReachable()) over path-based ones in modern Swift

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.