Mobile Development

Working with Files

There are instances where you need a more robust file store capability that NSUrlDefaults and plist files cannot help you with. This includes binary data like images and serialized custom class objects. For those instances, writing your own files to disk makes the most sense.

Once we begin working with our own files, more responsibility needs to be assumed. For instance, ensuring that a directory is created, deleting unused files and selecting an appropriate directory.

The Sandbox

iOS sandboxes each application, segregating application and user-generated data into its own directory. This is an important security feature of the iOS operating system. Each application is assigned a directory and within that directory a common structure applies:

Where to put files

iOS devices have a fixed amount of hard drive space. Your phone cannot be upgraded. People's phones accumulate a lot of data including imagery and videos, games and apps, documents and OS-specific files. Because of these constraints, Apple limits the amount of data your app can use. They do this in two ways.

  1. Any files placed within the tmp directory will be cleaned out by the operating system at an unknown time. Files placed within this directory should be able to be recreated easily.
  2. Any files that are not automatically cleaned up by iOS, i.e. files within the Documents directory, need to have as small of a footprint as possible. Apple has rejected apps from the iTunes App Store that take up too much space on the user's drive.

Reading Files

Reading a file is straight forward. Check that the file exists, then read it into a variable. Make sure you use the correct encoding. In our example, we are reading a JSON file, which is stored in plain text.

import Foundation

let path = NSTemporaryDirectory() + "advanced.json"
var jsonOutput:String?

if NSFileManager().fileExistsAtPath(path) {
    var err:NSError?
    jsonOutput = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: &err)
    if err != nil {
        NSLog("We read the following JSON from disk \(jsonOutput)")
    }
}

Saving Files and Creating Directories

Saving (or writing) files is also straight forward. Here we want to create the directory if it does not yet exist. Once we have completed that process, we can write to that directory. Here we define the encoding that we used in reading (above). Again, since our example is using a JSON file, we are wanting to write a string.

import Foundation

let path = NSTemporaryDirectory() + "advanced/advanced.json"

if !NSFileManager().fileExistsAtPath(path) {
    var err:NSError?
    NSFileManager().createDirectoryAtPath(path, withIntermediateDirectories: true, attributes: nil, error: &err)
}

let jsonOutput = "{'states': {'california': {'population_millions' ': 38.3,'square_miles' : 163696,'percent_water' : 4.3}}}"

var err:NSError?
let result = jsonOutput.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding, error: &err)

NSLog("We attempted to remove a file and our result was \(result)")

Deleting Files

To delete a file, simply ensure that it exists in a similar fashion as before and call the removeItemAtPath method. There is also a URL equivalent, should you not have a string directory reference.

import Foundation

let path = NSTemporaryDirectory() + "advanced.json"

if NSFileManager().fileExistsAtPath(path) {
    var err:NSError?
    let success = NSFileManager().removeItemAtPath(path, error: &err)
    NSLog("We attempted to remove a file and our result was \(success)")
}

Core data is next. Instead of managing files directly, we can use a central database stored on disk and replicated through iCloud.

References

NSCoding Tutorial for iOS: How To Save Your App Data http://www.raywenderlich.com/1914/nscoding-tutorial-for-ios-how-to-save-your-app-data

File System Programming Guide https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/Introduction/Introduction.html