How to find NSDocumentDirectory in Swift? - ios

I'm trying to get path to Documents folder with code:
var documentsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory:0,NSSearchPathDomainMask:0,true)
but Xcode gives error: Cannot convert expression's type 'AnyObject[]!' to type 'NSSearchPathDirectory'
I'm trying to understand what is wrong in the code.

Apparently, the compiler thinks NSSearchPathDirectory:0 is an array, and of course it expects the type NSSearchPathDirectory instead. Certainly not a helpful error message.
But as to the reasons:
First, you are confusing the argument names and types. Take a look at the function definition:
func NSSearchPathForDirectoriesInDomains(
directory: NSSearchPathDirectory,
domainMask: NSSearchPathDomainMask,
expandTilde: Bool) -> AnyObject[]!
directory and domainMask are the names, you are using the types, but you should leave them out for functions anyway. They are used primarily in methods.
Also, Swift is strongly typed, so you shouldn't just use 0. Use the enum's value instead.
And finally, it returns an array, not just a single path.
So that leaves us with (updated for Swift 2.0):
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
and for Swift 3:
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]

Swift 3.0 and 4.0
Directly getting first element from an array will potentially cause exception if the path is not found. So calling first and then unwrap is the better solution
if let documentsPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
//This gives you the string formed path
}
if let documentsPathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
//This gives you the URL of the path
}

The modern recommendation is to use NSURLs for files and directories instead of NSString based paths:
So to get the Document directory for the app as an NSURL:
func databaseURL() -> NSURL? {
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
if let documentDirectory: NSURL = urls.first as? NSURL {
// This is where the database should be in the documents directory
let finalDatabaseURL = documentDirectory.URLByAppendingPathComponent("items.db")
if finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) {
// The file already exists, so just return the URL
return finalDatabaseURL
} else {
// Copy the initial file from the application bundle to the documents directory
if let bundleURL = NSBundle.mainBundle().URLForResource("items", withExtension: "db") {
let success = fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL, error: nil)
if success {
return finalDatabaseURL
} else {
println("Couldn't copy file to final location!")
}
} else {
println("Couldn't find initial database in the bundle!")
}
}
} else {
println("Couldn't get documents directory!")
}
return nil
}
This has rudimentary error handling, as that sort of depends on what your application will do in such cases. But this uses file URLs and a more modern api to return the database URL, copying the initial version out of the bundle if it does not already exist, or a nil in case of error.

Xcode 8.2.1 • Swift 3.0.2
let documentDirectoryURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
Xcode 7.1.1 • Swift 2.1
let documentDirectoryURL = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)

Usually I prefer to use this extension:
Swift 3.x and Swift 4.0:
extension FileManager {
class func documentsDir() -> String {
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as [String]
return paths[0]
}
class func cachesDir() -> String {
var paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) as [String]
return paths[0]
}
}
Swift 2.x:
extension NSFileManager {
class func documentsDir() -> String {
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as [String]
return paths[0]
}
class func cachesDir() -> String {
var paths = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true) as [String]
return paths[0]
}
}

More convenient Swift 3 method:
let documentsUrl = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask).first!

For everyone who looks example that works with Swift 2.2, Abizern code with modern do try catch handle of error
func databaseURL() -> NSURL? {
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
if let documentDirectory:NSURL = urls.first { // No use of as? NSURL because let urls returns array of NSURL
// This is where the database should be in the documents directory
let finalDatabaseURL = documentDirectory.URLByAppendingPathComponent("OurFile.plist")
if finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) {
// The file already exists, so just return the URL
return finalDatabaseURL
} else {
// Copy the initial file from the application bundle to the documents directory
if let bundleURL = NSBundle.mainBundle().URLForResource("OurFile", withExtension: "plist") {
do {
try fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL)
} catch let error as NSError {// Handle the error
print("Couldn't copy file to final location! Error:\(error.localisedDescription)")
}
} else {
print("Couldn't find initial database in the bundle!")
}
}
} else {
print("Couldn't get documents directory!")
}
return nil
}
Update
I've missed that new swift 2.0 have guard(Ruby unless analog), so with guard it is much shorter and more readable
func databaseURL() -> NSURL? {
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
// If array of path is empty the document folder not found
guard urls.count != 0 else {
return nil
}
let finalDatabaseURL = urls.first!.URLByAppendingPathComponent("OurFile.plist")
// Check if file reachable, and if reacheble just return path
guard finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) else {
// Check if file is exists in bundle folder
if let bundleURL = NSBundle.mainBundle().URLForResource("OurFile", withExtension: "plist") {
// if exist we will copy it
do {
try fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL)
} catch let error as NSError { // Handle the error
print("File copy failed! Error:\(error.localizedDescription)")
}
} else {
print("Our file not exist in bundle folder")
return nil
}
return finalDatabaseURL
}
return finalDatabaseURL
}

Xcode 8b4 Swift 3.0
let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)

Usually i prefer like below in swift 3, because i can add file name and create a file easily
let fileManager = FileManager.default
if let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
let databasePath = documentsURL.appendingPathComponent("db.sqlite3").path
print("directory path:", documentsURL.path)
print("database path:", databasePath)
if !fileManager.fileExists(atPath: databasePath) {
fileManager.createFile(atPath: databasePath, contents: nil, attributes: nil)
}
}

Copy and paste this line in App delegate like this and it will print path like this
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
print(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! as String)
return true
}
Copy the path and paste it in go To Folder in finder by right clicking on it then enter
Open the file in Xcode

Related

Can users access files directly from iOS?

I am a beginner in iOS development.
I'm copying this by looking at an example of making a file.
override func viewDidLoad() {
super.viewDidLoad()
let fileName = "Test"
let DocumentDirURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileURL = DocumentDirURL.appendingPathComponent(fileName).appendingPathExtension("")
let writeString = "write test sting"
do {
try writeString.write(to: fileURL, atomically: true, encoding: String.Encoding.utf8)
} catch _ as NSError {
print("write error")
}
}
My question is that my current code is making and saving a file in document directory.
Can user see this file with user own eyes?
And is there anything else that I need to have permission to execute
this code?
This is an old Swift code. If there is a code that has a better way, please recommend it to me. Please help me a lot. Thank you in advance.
This will create a path of the directory you wanna saveit
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
if let documentDirectory: NSURL = urls.first as? NSURL {
// This is where the database should be in the documents directory
let finalDatabaseURL = documentDirectory.URLByAppendingPathComponent("items.db")
if finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) {
// The file already exists, so just return the URL
return finalDatabaseURL
} else {
// Copy the initial file from the application bundle to the documents directory
if let bundleURL = NSBundle.mainBundle().URLForResource("items", withExtension: "db") {
let success = fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL, error: nil)
if success {
return finalDatabaseURL
} else {
println("Cant found!")
}
} else {
println("Couldn't find !")
}
}
} else {
println("Couldn't get documents directory!")
}

Swift: How to copy files from app bundle to Documents folder when app runs for first time

There are all sorts of sample code & questions on SO dealing with how to programmatically copy files in Obj-C from the app bundle to the application's sandboxed Documents folder (e.g. here, here, and here) when the application runs for the first time.
How do you do this in Swift?
You could use FileManager API:
Here's example with a function that copies all files with specified extension:
func copyFilesFromBundleToDocumentsFolderWith(fileExtension: String) {
if let resPath = Bundle.main.resourcePath {
do {
let dirContents = try FileManager.default.contentsOfDirectory(atPath: resPath)
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
let filteredFiles = dirContents.filter{ $0.contains(fileExtension)}
for fileName in filteredFiles {
if let documentsURL = documentsURL {
let sourceURL = Bundle.main.bundleURL.appendingPathComponent(fileName)
let destURL = documentsURL.appendingPathComponent(fileName)
do { try FileManager.default.copyItem(at: sourceURL, to: destURL) } catch { }
}
}
} catch { }
}
}
Usage:
copyFilesFromBundleToDocumentsFolderWith(fileExtension: ".txt")
For Swift 4.2:
Assuming the file in your App Bundle is called Some File.txt
In ViewDidLoad, add:
let docName = "Some File"
let docExt = "txt"
copyFileToDocumentsFolder(nameForFile: docName, extForFile: docExt)
and then create a function as follows:
func copyFileToDocumentsFolder(nameForFile: String, extForFile: String) {
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
let destURL = documentsURL!.appendingPathComponent(nameForFile).appendingPathExtension(extForFile)
guard let sourceURL = Bundle.main.url(forResource: nameForFile, withExtension: extForFile)
else {
print("Source File not found.")
return
}
let fileManager = FileManager.default
do {
try fileManager.copyItem(at: sourceURL, to: destURL)
} catch {
print("Unable to copy file")
}
}

Remove all files from within documentDirectory in Swift

I am making an audio app, and the user can download files locally stored to the documentDirectory using FileManager.
Next, I'd like to allow the user to delete all files using a button. In the documentation, there is a method to remove items.
Here's my code:
#IBAction func deleteDirectoryButton(_ sender: Any) {
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
do {
try FileManager.default.removeItem(at: documentsUrl, includingPropertiesForKeys: nil, options: [])
} catch let error {
print(error)
}
}
Unfortunately, this won't build with an error Ambiguous reference to member 'removeItem(atPath:)'.
Is there a better approach to access the documentDirectory and remove all files from the directory in one swoop?
First of all the error occurs because the signature of the API is wrong. It's just removeItem(at:) without the other parameters.
A second issue is that you are going to delete the Documents directory itself rather than the files in the directory which you are discouraged from doing that.
You have to get the contents of the directory and add a check for example to delete only MP3 files. A better solution would be to use a subfolder.
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
do {
let fileURLs = try FileManager.default.contentsOfDirectory(at: documentsUrl,
includingPropertiesForKeys: nil,
options: .skipsHiddenFiles)
for fileURL in fileURLs where fileURL.pathExtension == "mp3" {
try FileManager.default.removeItem(at: fileURL)
}
} catch { print(error) }
Side note: It is highly recommended to use always the URL related API of FileManager.
Try this
func clearAllFiles() {
let fileManager = FileManager.default
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
print("Directory: \(paths)")
do {
let fileName = try fileManager.contentsOfDirectory(atPath: paths)
for file in fileName {
// For each file in the directory, create full path and delete the file
let filePath = URL(fileURLWithPath: paths).appendingPathComponent(file).absoluteURL
try fileManager.removeItem(at: filePath)
}
} catch let error {
print(error)
}
}
Just use code as Follow
to save AudioFile in Document Directory as
func getDocumentsDirectory() -> URL
{
//Get Basic URL
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
/// Enter a Directory Name in which files will be saved
let dataPath1 = documentsDirectory.appendingPathComponent("folder_name_enter")
let dataPath = dataPath1.appendingPathComponent("folder inside directory if required (name)")
//Handler
do
{
try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
}
catch let error as NSError
{
print("Error creating directory: \(error.localizedDescription)")
}
return dataPath
}
Delete
func clearAllFilesFromTempDirectory()
{
let fileManager = FileManager.default
let dirPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let tempDirPath = dirPath.appending("/folder_name/\(inside_directoryName)")
do {
let folderPath = tempDirPath
let paths = try fileManager.contentsOfDirectory(atPath: tempDirPath)
for path in paths
{
try fileManager.removeItem(atPath: "\(folderPath)/\(path)")
}
}
catch let error as NSError
{
print(error.localizedDescription)
}
}
Saving Method
getDocumentsDirectory().appendingPathComponent("\(audioName).wav")
Deletion Method
/// Just call
clearAllFilesFromTempDirectory
This my extension for remove all files and caches from directory.
// MARK: - FileManager extensions
extension FileManager {
/// Remove all files and caches from directory.
public static func removeAllFilesDirectory() {
let fileManager = FileManager()
let mainPaths = [
FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).map(\.path)[0],
FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).map(\.path)[0]
]
mainPaths.forEach { mainPath in
do {
let content = try fileManager.contentsOfDirectory(atPath: mainPath)
content.forEach { file in
do {
try fileManager.removeItem(atPath: URL(fileURLWithPath: mainPath).appendingPathComponent(file).path)
} catch {
// Crashlytics.crashlytics().record(error: error)
}
}
} catch {
// Crashlytics.crashlytics().record(error: error)
}
}
}
}
Swift 5
Delete the whole folder:
If you'd like to delete a whole folder you can simply do this:
func deleteFolder(_ folderName: String, completion: () -> Void) {
let fileManager = FileManager.default
let directory = fileManager.cachesDirectory().appendingPathComponent(folderName)
_ = try? fileManager.removeItem(at: directory)
completion()
}
Delete certain files based on their name:
This will loop through all the files and remove all that contain the
func removeFiles(containing: String, completion: () -> Void) {
let fileManager = FileManager.default
let directory = fileManager.cachesDirectory()
if let fileNames = try? fileManager.contentsOfDirectory(atPath: directory.path) {
for file in fileNames {
if file.contains(containing) {
let filePath = URL(fileURLWithPath: directory.path).appendingPathComponent(file).absoluteURL
_ = try? fileManager.removeItem(at: filePath)
}
}
}
completion()
}

appendingPathComponent' is unavailable: Use appendingPathComponent on URL instead.a

I am using Swift 4, Xcode 9, and development target iOS 11.0.
I am trying to append a custom folder (MyFolder) to the path variable.
let outputFilePath = (NSTemporaryDirectory() as NSString).appending("MyFolder").appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!)
But builder is giving error message:
appendingPathComponent' is unavailable: Use appendingPathComponent on URL instead.
I know, I am doing some silly mistake. Can you kindly help me in this?
Use this line
URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("MyFolder").appendingPathComponent(outputFileName).appendingPathExtension("mov")
instead of
(NSTemporaryDirectory() as NSString).appending("MyFolder").appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!)
This will return you a url and use url.Path to get its path in string .
Hope this helps you.
Check below code for reference in document Directory
class func getDocumentsDirectory() -> URL {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let dataPath = documentsDirectory.appendingPathComponent("FolderName")
do {
try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print("Error creating directory: \(error.localizedDescription)")
}
return dataPath
}
For Appending Files in Folder You can use this
//name for file to be added
let uuid = UUID().uuidString
// storing a Audio File in Directory
let audioFilename = getDocumentsDirectory().appendingPathComponent("\(uuid).m4a")
To get Names of Files Available in the respected Folder created
//This function returns a Array with file names Available
class func getListOfRecordingsAvailable() -> [String] {
var fileNameArray = [String]()
let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let myFilesPath = documentDirectoryPath.appending("/FolderName")
let files = FileManager.default.enumerator(atPath: myFilesPath)
while let file = files?.nextObject() {
//myfilesPath - Path
//file - fileName
fileNameArray.append(file as! String)
}
print(fileNameArray)
return fileNameArray
}

How to check if a file exists in the Documents directory in Swift?

How to check if a file exists in the Documents directory in Swift?
I am using [ .writeFilePath ] method to save an image into the Documents directory and I want to load it every time the app is launched. But I have a default image if there is no saved image.
But I just cant get my head around how to use the [ func fileExistsAtPath(_:) ] function. Could someone give an example of using the function with a path argument passed into it.
I believe I don't need to paste any code in there as this is a generic question. Any help will be much appreciated.
Swift 4.x version
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
if let pathComponent = url.appendingPathComponent("nameOfFileHere") {
let filePath = pathComponent.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
print("FILE AVAILABLE")
} else {
print("FILE NOT AVAILABLE")
}
} else {
print("FILE PATH NOT AVAILABLE")
}
Swift 3.x version
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = URL(fileURLWithPath: path)
let filePath = url.appendingPathComponent("nameOfFileHere").path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
print("FILE AVAILABLE")
} else {
print("FILE NOT AVAILABLE")
}
Swift 2.x version, need to use URLByAppendingPathComponent
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.URLByAppendingPathComponent("nameOfFileHere").path!
let fileManager = NSFileManager.defaultManager()
if fileManager.fileExistsAtPath(filePath) {
print("FILE AVAILABLE")
} else {
print("FILE NOT AVAILABLE")
}
Check the below code:
Swift 1.2
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let getImagePath = paths.stringByAppendingPathComponent("SavedFile.jpg")
let checkValidation = NSFileManager.defaultManager()
if (checkValidation.fileExistsAtPath(getImagePath))
{
println("FILE AVAILABLE");
}
else
{
println("FILE NOT AVAILABLE");
}
Swift 2.0
let paths = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let getImagePath = paths.URLByAppendingPathComponent("SavedFile.jpg")
let checkValidation = NSFileManager.defaultManager()
if (checkValidation.fileExistsAtPath("\(getImagePath)"))
{
print("FILE AVAILABLE");
}
else
{
print("FILE NOT AVAILABLE");
}
Nowadays (2016) Apple recommends more and more to use the URL related API of NSURL, NSFileManager etc.
To get the documents directory in iOS and Swift 2 use
let documentDirectoryURL = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory,
inDomain: .UserDomainMask,
appropriateForURL: nil,
create: true)
The try! is safe in this case because this standard directory is guaranteed to exist.
Then append the appropriate path component for example an sqlite file
let databaseURL = documentDirectoryURL.URLByAppendingPathComponent("MyDataBase.sqlite")
Now check if the file exists with checkResourceIsReachableAndReturnError of NSURL.
let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)
If you need the error pass the NSError pointer to the parameter.
var error : NSError?
let fileExists = databaseURL.checkResourceIsReachableAndReturnError(&error)
if !fileExists { print(error) }
Swift 3+:
let documentDirectoryURL = try! FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true)
let databaseURL = documentDirectoryURL.appendingPathComponent("MyDataBase.sqlite")
checkResourceIsReachable is marked as can throw
do {
let fileExists = try databaseURL.checkResourceIsReachable()
// handle the boolean result
} catch let error as NSError {
print(error)
}
To consider only the boolean return value and ignore the error use the nil-coalescing operator
let fileExists = (try? databaseURL.checkResourceIsReachable()) ?? false
Swift 4.2
extension URL {
func checkFileExist() -> Bool {
let path = self.path
if (FileManager.default.fileExists(atPath: path)) {
print("FILE AVAILABLE")
return true
}else {
print("FILE NOT AVAILABLE")
return false;
}
}
}
Using: -
if fileUrl.checkFileExist()
{
// Do Something
}
It's pretty user friendly. Just work with NSFileManager's defaultManager singleton and then use the fileExistsAtPath() method, which simply takes a string as an argument, and returns a Bool, allowing it to be placed directly in the if statement.
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentDirectory = paths[0] as! String
let myFilePath = documentDirectory.stringByAppendingPathComponent("nameOfMyFile")
let manager = NSFileManager.defaultManager()
if (manager.fileExistsAtPath(myFilePath)) {
// it's here!!
}
Note that the downcast to String isn't necessary in Swift 2.
works at Swift 5
do {
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileUrl = documentDirectory.appendingPathComponent("userInfo").appendingPathExtension("sqlite3")
if FileManager.default.fileExists(atPath: fileUrl.path) {
print("FILE AVAILABLE")
} else {
print("FILE NOT AVAILABLE")
}
} catch {
print(error)
}
where "userInfo" - file's name, and "sqlite3" - file's extension
An alternative/recommended Code Pattern in Swift 3 would be:
Use URL instead of FileManager
Use of exception handling
func verifyIfSqliteDBExists(){
let docsDir : URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let dbPath : URL = docsDir.appendingPathComponent("database.sqlite")
do{
let sqliteExists : Bool = try dbPath.checkResourceIsReachable()
print("An sqlite database exists at this path :: \(dbPath.path)")
}catch{
print("SQLite NOT Found at :: \(strDBPath)")
}
}
Swift 5
extension FileManager {
class func fileExists(filePath: String) -> Bool {
var isDirectory = ObjCBool(false)
return self.default.fileExists(atPath: filePath, isDirectory: &isDirectory)
}
}
Very simple:
If your path is a URL instance convert to string by 'path' method.
let fileManager = FileManager.default
var isDir: ObjCBool = false
if fileManager.fileExists(atPath: yourURLPath.path, isDirectory: &isDir) {
if isDir.boolValue {
//it's a Directory path
}else{
//it's a File path
}
}
For the benefit of Swift 3 beginners:
Swift 3 has done away with most of the NextStep syntax
So NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain are no longer used
Instead use URL and FileManager
NSSearchPathForDirectoriesInDomain is not needed
Instead use FileManager.default.urls
Here is a code sample to verify if a file named "database.sqlite" exists in application document directory:
func findIfSqliteDBExists(){
let docsDir : URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let dbPath : URL = docsDir.appendingPathComponent("database.sqlite")
let strDBPath : String = dbPath.path
let fileManager : FileManager = FileManager.default
if fileManager.fileExists(atPath:strDBPath){
print("An sqlite database exists at this path :: \(strDBPath)")
}else{
print("SQLite NOT Found at :: \(strDBPath)")
}
}
This works fine for me in swift4:
func existingFile(fileName: String) -> Bool {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
if let pathComponent = url.appendingPathComponent("\(fileName)") {
let filePath = pathComponent.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath)
{
return true
} else {
return false
}
} else {
return false
}
}
You can check with this call:
if existingFile(fileName: "yourfilename") == true {
// your code if file exists
} else {
// your code if file does not exist
}
I hope it is useful for someone. #;-]
You must add a "/" slash before filename, or you get path like ".../DocumentsFilename.jpg"
Swift 4 example:
var filePath: String {
//manager lets you examine contents of a files and folders in your app.
let manager = FileManager.default
//returns an array of urls from our documentDirectory and we take the first
let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first
//print("this is the url path in the document directory \(String(describing: url))")
//creates a new path component and creates a new file called "Data" where we store our data array
return(url!.appendingPathComponent("Data").path)
}
I put the check in my loadData function which I called in viewDidLoad.
override func viewDidLoad() {
super.viewDidLoad()
loadData()
}
Then I defined loadData below.
func loadData() {
let manager = FileManager.default
if manager.fileExists(atPath: filePath) {
print("The file exists!")
//Do what you need with the file.
ourData = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as! Array<DataObject>
} else {
print("The file DOES NOT exist! Mournful trumpets sound...")
}
}

Resources