iOS Development

Course No. 10-152-139

Chapter 26 — Writing Files with NSString and NSData

Writing an NSString to a file

  • Here’s the simple way to write a string to a file. We’ve seen this before.
  • More detail
  • Using a mutable string. They are generally faster to manipulate.
  • Create a bigger string by appending to our mutable string.
  • Now we write the string to the file system.
  • Let’s break this down step by step.
  • First we use an absolute reference to someplace in our file system.
  • Writing this string atomically means that the string will be written to a temporary file first. If that step is successful then a file already named cool.txt will be deleted and our new temporary file will be renamed.
  • There are lots of was to have text in a file. These formats are called encodings. The NSUTF8StringEncoding is a very common one. Pick this one if you don’t know what the encoding is for a file.
  • This ignores any potential errors. Do you think this is a good idea? I didn’t think so.

NSError

  • We’re going to add error handling to the previous example. This same approach will apply to lots of other situations.
  • Let’s start by looking at the documentation for the writeToFile:atomically:encoding:error: method.
    • writeToFile:atomically:encoding:error:
      Writes the contents of the receiver to a file at a given path using a given encoding.
    • - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error
    • Parameters
      • path
        The file to which to write the receiver. If path contains a tilde (~) character, you must expand it with stringByExpandingTildeInPath before invoking this method.
      • useAuxiliaryFile
        If YES, the receiver is written to an auxiliary file, and then the auxiliary file is renamed to path. If NO, the receiver is written directly to path. The YES option guarantees that path, if it exists at all, won’t be corrupted even if the system should crash during writing.
      • enc
        The encoding to use for the output.
      • error
        If there is an error, upon return contains an NSError object that describes the problem. If you are not interested in details of errors, you may pass in NULL.
    • Return Value
      YES if the file is written successfully, otherwise NO (if there was a problem writing to the file or with the encoding).
  • Notice that the method returns a BOOL. If the method return YES then the write was successful. The first version of our example was ignoring this.

Version 2!

  • Here’s the example rewritten with error handling.
  • Here’s what’s new in the code.
  • Create a pointer to an NSError object. There’s no object yet, it’s just an empty pointer after this line of code.
  • Next, we capture the return value of the write method.
  • Now we have the line that’s hard to explain if we hadn’t learned so much C earlier in the semester.
    • If we didn’t make the NSError object where did it come from? It will be created in the writeToFile:atomically:encoding:error: method if the write fails.
    • If the write is successful no NSError object will be created.
  • Finally, we test for success.
  • Let’s look at the declaration of the write method again.
    • - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error
  • See this? error:(NSError **)error
  • The two asterisks, **, mean that you have to send the address of a pointer to a method. This is a common Objective-C idiom.

Reading files with NSString

  • Reading files has a very similar pattern.
  • We’ll see this in many places in the Foundation classes.

Writing an NSData object to a file

  • We also can write binary data like images with the writeToFile: method.

Reading an NSData from a file

  • Reading a binary file is pretty easy, too.

Finding special directories

  • Files are typically saved to specific directories that users expect.
  • Downloaded files from a browser are saved by default to a user’s Downloads directory (e.g. /Users/<user>/Downloads/).
  • Apple created a function that will give you the directory for the correct purpose. Here is how you get the path to the user’s Desktop directory.
  • Other special directories. Here are some of the common constants:
    • NSApplicationDirectory
    • NSLibraryDirectory
    • NSUserDirectory
    • NSDocumentDirectory
    • NSDesktopDirectory
    • NSCachesDirectory
    • NSApplicationSupportDirectory
    • NSDownloadsDirectory
    • NSMoviesDirectory
    • NSMusicDirectory
    • NSPicturesDirectory
    • NSTrashDirectory