Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Adding email attachments in swift.

I am creating an app that requires to store data in a .txt file. Data is collected and stored in arrays. I need help in creating a txt file that will contain the data in the file.

I have the following code so far but is not attaching the txt file.

//this is the file. we will write to and read from it
    let fileName = "data.txt"

    //Function to create a test file that contains data from the accelerometer.
    func createTestFile(){

        if let dir : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
        let path = dir.stringByAppendingPathComponent(fileName);

            //writing
            do {
                try data.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding)
            }
            catch {/* error handling here */}
        }

    }


if let filePath = NSBundle.mainBundle().pathForResource(fileName, ofType: "text/plain"){
            if let fileData = NSData(contentsOfFile: filePath){
                mailComposer.addAttachmentData(fileData, mimeType: "text/plain", fileName: fileName)
            }
        }

Any help is appreciated, thanks!

3 Answers

There are lots of tutorials... but treehouse has some of the best.

If you look at your code... you are saving it by calling:

if let dir : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
        let path = dir.stringByAppendingPathComponent(fileName);

            //writing
            do {
                try data.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding)
            }
            catch {/* error handling here */}
        }

    }

Notice... no where in there are you saving to the application BUNDLE. You are saving in the filesystem of the OS under the documents directory.

Think of the documents directory as the documents directory on your computer, and the bundle as being the application file that you would launch.

When you are trying to load the file you are saying:

  if let filePath = NSBundle.mainBundle().pathForResource(fileName, ofType: "text/plain"){
            if let fileData = NSData(contentsOfFile: filePath){
                mailComposer.addAttachmentData(fileData, mimeType: "text/plain", fileName: fileName)
            }
        }

When you look at the code you are not even referencing the same location at all.

What your code is doing is equivalent to the following on your computer:

-Save file to documents folder with name "test.doc"

-Load file named "test.doc" that is compiled in the application "Word"

So...

NSFileManager = FileSystem and the contents that make it up

NSBundle = Application and the contents that make it up

It doesn't make sense that your file test.doc would have shipped with the Word application.

Rather consider the following: (put this in a simulator and try it... the print statements will show you the file paths are identical)

class FileTest {
    let directories = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    let fileName = "test.doc"

    func saveFile(dataToSave: NSData) {
        guard let directory = directories.first else { return }
        let fileSaveLocation = NSURL(fileURLWithPath: fileName , relativeToURL: directory)

        dataToSave.writeToURL(fileSaveLocation, atomically: true)
        print("*** file saved to path: \(fileSaveLocation)")
    }

    func loadFile() -> NSData? {
        guard let directory = directories.first else { return nil }
        let fileLocationForLoad = NSURL(fileURLWithPath: fileName, relativeToURL: directory)

        print("*** file loading from path: \(fileLocationForLoad)")
        return NSData(contentsOfURL: fileLocationForLoad)
    }
}

In your if let statement you are searching for the file in a different location than where you are saving it. You will want to use the same path for both saving and loading.

Hope this helps...

I think I am doing that, am I not? Code looks okay. Not sure what is wrong.

:-)

Your not... you are saving in the Documents directory of the user domain that iOS is assigning for the Application. This is different than the bundle which refers to the bundle of resources/files that make up the application. This bundle contains all the class files, image assets, and other files like the Info.plist file for the application.

Make sense?

If not, check out the documentation for NSBundle, and NSFileManager.

Let me know if that helps!

(*** Also it might be worth adding some print statements that show the different locations in the file system so that you can see that they are pointing to different locations. ***)

I can't get it to work, is there a tutorial that you recommend that has a similar lesson for it. I am new to this file system. I appreciate your help. Thanks.