15
Saving, Loading, and Multitasking

Every iOS application has its own application sandbox. An application sandbox is a directory on the filesystem that is barricaded from the rest of the filesystem. Your application must stay in its sandbox, and no other application can access your sandbox.

Application Sandbox

Figure 15.1  Application sandbox

Application sandbox

The application sandbox contains a number of directories:

application bundle

This directory contains all the resources and the executable. It is read-only.

Library/Preferences/

This directory is where any preferences are stored and where the Settings application looks for application preferences. Library/Preferences is handled automatically by the class NSUserDefaults (which you will learn about in Chapter 19) and is backed up when the device is synchronized with iTunes.

tmp/

This directory is where you write data that you will use temporarily during an application’s runtime. You should remove files from this directory when done with them, and the operating system may purge them while your application is not running. It does not get backed up when the device is synchronized with iTunes. To get the path to the tmp directory in the application sandbox, you can use the convenience function NSTemporaryDirectory.

Documents/

This directory is where you write data that the application generates during runtime and that you want to persist between runs of the application. It is backed up when the device is synchronized with iTunes. If something goes wrong with the device, files in this directory can be restored from iTunes. For example, in a game application, the saved game files would be stored here.

Library/Caches/

This directory is where you write data that the application generates during runtime and that you want to persist between runs of the application. However, unlike the Documents directory, it does not get backed up when the device is synchronized with iTunes. A major reason for not backing up cached data is that the data can be very large and extend the time it takes to synchronize your device. Data stored somewhere else – like a web server – can be placed in this directory. If the user needs to restore the device, this data can be downloaded from the web server again.

Constructing a file path

We want Possessions to persist in Homepwner. (It’s not much fun if you have to enter all your possessions every time you start the application.) The data for the Possessions will be saved and loaded into a single file in the Documents directory of Homepwner’s sandbox. The PossessionStore will handle writing to and reading from the filesystem. To do this, the PossessionStore needs a path to the file in Documents containing the Possession data.

To get the full path for a directory in the sandbox, you use the C function NSSearchPathForDirectoriesInDomains. This function takes three parameters: the type of directory, the domain mask, and a boolean value that decides if it should expand a tilde (~) if one exists in the path. The first parameter is an NSSearchPathDirectory constant. The last two parameters are always the same on iOS: NSUserDomainMask and YES. For instance, to get the Documents directory for an application, you would call the function as follows:

 ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​d​o​c​u​m​e​n​t​P​a​t​h​s​ ​=​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​S​e​a​r​c​h​P​a​t​h​F​o​r​D​i​r​e​c​t​o​r​i​e​s​I​n​D​o​m​a​i​n​s​(​N​S​D​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​U​s​e​r​D​o​m​a​i​n​M​a​s​k​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​Y​E​S​)​;​
 ​ ​ ​ ​N​S​S​t​r​i​n​g​ ​*​o​u​r​D​o​c​u​m​e​n​t​P​a​t​h​ ​=​ ​[​d​o​c​u​m​e​n​t​P​a​t​h​s​ ​o​b​j​e​c​t​A​t​I​n​d​e​x​:​0​]​;​

Notice that NSSearchPathForDirectoriesInDomains returns an NSArray. This is because this function comes from Mac OS X where there could be multiple directories for the parameters. In iOS, however, there is only one directory for the possible constants, and it is safe to grab the first NSString from the array.

You can also get the path for the sandbox itself using the function NSHomeDirectory. Note that you cannot write files or create directories at the root-level of the sandbox. Any new directories or files must be created within one of the writeable directories in the sandbox: Documents, Library, or tmp. You can append the names of the directories to the string returned from this function.

N​S​S​t​r​i​n​g​ ​*​s​a​n​d​b​o​x​P​a​t​h​ ​=​ ​N​S​H​o​m​e​D​i​r​e​c​t​o​r​y​(​)​;​
/​/​ ​O​n​c​e​ ​y​o​u​ ​h​a​v​e​ ​t​h​e​ ​f​u​l​l​ ​s​a​n​d​b​o​x​ ​p​a​t​h​,​ ​y​o​u​ ​c​a​n​ ​c​r​e​a​t​e​ ​a​ ​p​a​t​h​ ​f​r​o​m​ ​i​t​
N​S​S​t​r​i​n​g​ ​*​d​o​c​u​m​e​n​t​P​a​t​h​ ​=​ ​[​s​a​n​d​b​o​x​P​a​t​h​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​s​t​r​i​n​g​B​y​A​p​p​e​n​d​i​n​g​P​a​t​h​C​o​m​p​o​n​e​n​t​:​@​"​D​o​c​u​m​e​n​t​s​"​]​;​

However, it is safer to use NSSearchPathForDirectoriesInDomains than NSHomeDirectory with an appended directory name. The name of a directory could change in future releases of the operating system or you could mistype the string you are appending.

Open the Homepwner project. In PossessionStore.h, declare a new method that specifies the name of the file on the filesystem that contains the data for all of the Possessions.

-​ ​(​N​S​S​t​r​i​n​g​ ​*​)​p​o​s​s​e​s​s​i​o​n​A​r​c​h​i​v​e​P​a​t​h​;​

In PossessionStore.m, implement this method so that it returns the full path to where the Possessions will be stored.

-​ ​(​N​S​S​t​r​i​n​g​ ​*​)​p​o​s​s​e​s​s​i​o​n​A​r​c​h​i​v​e​P​a​t​h​
{​
 ​ ​ ​ ​/​/​ ​T​h​e​ ​r​e​t​u​r​n​e​d​ ​p​a​t​h​ ​w​i​l​l​ ​b​e​ ​S​a​n​d​b​o​x​/​D​o​c​u​m​e​n​t​s​/​p​o​s​s​e​s​s​i​o​n​s​.​d​a​t​a​
 ​ ​ ​ ​/​/​ ​B​o​t​h​ ​t​h​e​ ​s​a​v​i​n​g​ ​a​n​d​ ​l​o​a​d​i​n​g​ ​m​e​t​h​o​d​s​ ​w​i​l​l​ ​c​a​l​l​ ​t​h​i​s​ ​m​e​t​h​o​d​ ​t​o​ ​g​e​t​ ​t​h​e​ ​s​a​m​e​ ​p​a​t​h​,​
 ​ ​ ​ ​/​/​ ​p​r​e​v​e​n​t​i​n​g​ ​a​ ​t​y​p​o​ ​i​n​ ​t​h​e​ ​p​a​t​h​ ​n​a​m​e​ ​o​f​ ​e​i​t​h​e​r​ ​m​e​t​h​o​d​

 ​ ​ ​ ​r​e​t​u​r​n​ ​p​a​t​h​I​n​D​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​(​@​"​p​o​s​s​e​s​s​i​o​n​s​.​d​a​t​a​"​)​;​
}​

Notice the pathInDocumentDirectory function. That’s what you’ll create next. This function will return the full path of a file in the Documents directory when given the name of that file. It is not a part of an Objective-C class but a stand-alone C function. You’ll use this function many different places, so create a separate file for it. Use the NSObject template like before (FileNewNew File...) and name your subclass FileHelpers.

Now you’re going to remove the class interface and implementation from the two files. (The NSObject template is just a quick and easy way to create two new files with .h and .m suffixes.) Open FileHelpers.h, delete the interface declaration, and declare the new function. The file should look just like this:

#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​

N​S​S​t​r​i​n​g​ ​*​p​a​t​h​I​n​D​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​(​N​S​S​t​r​i​n​g​ ​*​f​i​l​e​N​a​m​e​)​;​

In FileHelpers.m, delete the implementation block and define the pathInDocumentDirectory function. FileHelpers.m should look exactly like this:

#​i​m​p​o​r​t​ ​"​F​i​l​e​H​e​l​p​e​r​s​.​h​"​

/​/​ ​T​o​ ​u​s​e​ ​t​h​i​s​ ​f​u​n​c​t​i​o​n​,​ ​y​o​u​ ​p​a​s​s​ ​i​t​ ​a​ ​f​i​l​e​ ​n​a​m​e​,​ ​a​n​d​ ​i​t​ ​w​i​l​l​ ​c​o​n​s​t​r​u​c​t​
/​/​ ​t​h​e​ ​f​u​l​l​ ​p​a​t​h​ ​f​o​r​ ​t​h​a​t​ ​f​i​l​e​ ​i​n​ ​t​h​e​ ​D​o​c​u​m​e​n​t​s​ ​d​i​r​e​c​t​o​r​y​.​
N​S​S​t​r​i​n​g​ ​*​p​a​t​h​I​n​D​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​(​N​S​S​t​r​i​n​g​ ​*​f​i​l​e​N​a​m​e​)​
{​
 ​ ​ ​ ​/​/​ ​G​e​t​ ​l​i​s​t​ ​o​f​ ​d​o​c​u​m​e​n​t​ ​d​i​r​e​c​t​o​r​i​e​s​ ​i​n​ ​s​a​n​d​b​o​x​
 ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​d​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​i​e​s​ ​=​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​S​e​a​r​c​h​P​a​t​h​F​o​r​D​i​r​e​c​t​o​r​i​e​s​I​n​D​o​m​a​i​n​s​(​N​S​D​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​U​s​e​r​D​o​m​a​i​n​M​a​s​k​,​ ​Y​E​S​)​;​

 ​ ​ ​ ​/​/​ ​G​e​t​ ​o​n​e​ ​a​n​d​ ​o​n​l​y​ ​d​o​c​u​m​e​n​t​ ​d​i​r​e​c​t​o​r​y​ ​f​r​o​m​ ​t​h​a​t​ ​l​i​s​t​
 ​ ​ ​ ​N​S​S​t​r​i​n​g​ ​*​d​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​ ​=​ ​[​d​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​i​e​s​ ​o​b​j​e​c​t​A​t​I​n​d​e​x​:​0​]​;​

 ​ ​ ​ ​/​/​ ​A​p​p​e​n​d​ ​p​a​s​s​e​d​ ​i​n​ ​f​i​l​e​ ​n​a​m​e​ ​t​o​ ​t​h​a​t​ ​d​i​r​e​c​t​o​r​y​,​ ​r​e​t​u​r​n​ ​i​t​
 ​ ​ ​ ​r​e​t​u​r​n​ ​[​d​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​ ​s​t​r​i​n​g​B​y​A​p​p​e​n​d​i​n​g​P​a​t​h​C​o​m​p​o​n​e​n​t​:​f​i​l​e​N​a​m​e​]​;​
}​

This function will eventually be called from a number of different files and will have to be imported into each file that uses it, which is a bit of a nuisance. We can avoid this nuisance by importing FileHelpers.h into Homepwner’s precompiled header file. Every project has a precompiled header file (.pch), and this file is imported into every file in the project. Open Homepwner-Prefix.pch from the project navigator and import FileHelpers.h.

#​i​f​d​e​f​ ​_​_​O​B​J​C​_​_​
 ​ ​ ​ ​#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​
 ​ ​ ​ ​#​i​m​p​o​r​t​ ​<​U​I​K​i​t​/​U​I​K​i​t​.​h​>​
 ​ ​ ​ ​#​i​m​p​o​r​t​ ​"​F​i​l​e​H​e​l​p​e​r​s​.​h​"​
#​e​n​d​i​f​

Now every file in the Homepwner project will effectively import FileHelpers.h. Note that if you modify a file that is imported in the precompiled header file, it forces your entire project to be recompiled. Thus, you should only import files into the precompiled header file that rarely or never change.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.9.124