Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access file included in app bundle in Swift?

I know there are a few questions pertaining to this, but they're in Objective-C.

How can I access a .txt file included in my app using Swift on an actual iPhone? I want to be able to read and write from it. Here are my project files if you want to take a look. I'm happy to add details if necessary.

like image 341
atirit Avatar asked Jun 01 '16 22:06

atirit


People also ask

What is the use of bundle in Swift?

The bundle object provides a single interface for locating items, taking into account the bundle structure, user preferences, available localizations, and other relevant factors. Any executable can use a bundle object to locate resources, either inside an app's bundle or in a known bundle located elsewhere.

What is main bundle in Swift?

The main bundle lets you access the resources in the same directory as the currently running executable.


2 Answers

Simply by searching in the app bundle for the resource

var filePath = NSBundle.mainBundle().URLForResource("file", withExtension: "txt") 

However you can't write to it because it is in the app resources directory and you have to create it in the document directory to write to it

var documentsDirectory: NSURL? var fileURL: NSURL?  documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).last! fileURL = documentsDirectory!.URLByAppendingPathComponent("file.txt")  if (fileURL!.checkResourceIsReachableAndReturnError(nil)) {     print("file exist") }else{     print("file doesnt exist")     NSData().writeToURL(fileURL!,atomically:true) } 

now you can access it from fileURL

EDIT - 28 August 2018

This is how to do it in Swift 4.2

var filePath = Bundle.main.url(forResource: "file", withExtension: "txt") 

To create it in the document directory

if let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {    let fileURL = documentsDirectory.appendingPathComponent("file.txt")    do {        if try fileURL.checkResourceIsReachable() {            print("file exist")        } else {            print("file doesnt exist")            do {             try Data().write(to: fileURL)            } catch {                print("an error happened while creating the file")            }        }    } catch {        print("an error happened while checking for the file")    } } 
like image 166
Karim H Avatar answered Sep 28 '22 10:09

Karim H


Swift 3, based on Karim’s answer.

Reading

You can read files included in an app’s bundle through the bundle’s resource:

let fileURL = Bundle.main.url(forResource:"filename", withExtension: "txt") 

Writing

However, you can’t write there. You will need to create a copy, preferably in the Documents directory:

func makeWritableCopy(named destFileName: String, ofResourceFile originalFileName: String) throws -> URL {     // Get Documents directory in app bundle     guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last else {         fatalError("No document directory found in application bundle.")     }      // Get URL for dest file (in Documents directory)     let writableFileURL = documentsDirectory.appendingPathComponent(destFileName)      // If dest file doesn’t exist yet     if (try? writableFileURL.checkResourceIsReachable()) == nil {         // Get original (unwritable) file’s URL         guard let originalFileURL = Bundle.main.url(forResource: originalFileName, withExtension: nil) else {             fatalError("Cannot find original file “\(originalFileName)” in application bundle’s resources.")         }          // Get original file’s contents         let originalContents = try Data(contentsOf: originalFileURL)          // Write original file’s contents to dest file         try originalContents.write(to: writableFileURL, options: .atomic)         print("Made a writable copy of file “\(originalFileName)” in “\(documentsDirectory)\\\(destFileName)”.")      } else { // Dest file already exists         // Print dest file contents         let contents = try String(contentsOf: writableFileURL, encoding: String.Encoding.utf8)         print("File “\(destFileName)” already exists in “\(documentsDirectory)”.\nContents:\n\(contents)")     }      // Return dest file URL     return writableFileURL } 

Example usage:

let stuffFileURL = try makeWritableCopy(named: "Stuff.txt", ofResourceFile: "Stuff.txt") try "New contents".write(to: stuffFileURL, atomically: true, encoding: String.Encoding.utf8) 
like image 45
Philippe-André Lorin Avatar answered Sep 28 '22 11:09

Philippe-André Lorin