File and Data Management - IPHONE APPS

Files in iPhone OS share space with the user’s media and personal files on the flash-based memory. For security purposes, your application is placed in its own directory and is limited to reading and writing files in that directory only. The following sections describe the structure of an application’s local file system and several techniques for reading and writing files.

Commonly Used Directories

For security purposes, an application has only a few locations in which it can write its data and preferences. When an application is installed on a device, a home directory is created for the application. Table lists some of the important subdirectories inside the home directory that you might need to access. This table describes the intended usage and access restrictions for each directory and whether the directory’s contents are backed up by iTunes. For more information about the backup and restore process, see “Backup and Restore”. For more information about the application home directory itself, see “The Application Sandbox”.

Directories of an iPhone application

Directories of an iPhone application

Backup and Restore

You do not have to prepare your application in any way for backup and restore operations. In iPhone OS 2.2 and later, when a device is plugged into a computer and synced, iTunes performs an incremental backup of all files, except for those in the following directories:

  • <Application_Home>/
  • <Application_Home>/Library/Caches
  • <Application_Home>/tmp

Although iTunes does back up the application bundle itself, it does not do this during every sync operation. Applications purchased from the App Store on the device are backed up when that device is next synced with iTunes. Applications are not backed up during subsequent sync operations though unless the application bundle itself has changed(because the application was updated, for example).

To prevent the syncing process from taking a long time, you should be selective about where you place files inside your application’s home directory. The <Application_ Home>/ Documents directory should be used to store user data files or files that cannot be easily recreated by your application. Files used to store temporary data should be placed inside the Application Home/tmp directory and deleted by your application when they are no longer needed. If your application creates data files that can be used during subsequent launches, it should place those files in the Application Home/ Library/ Caches directory.

Files Saved During Application Updates

Updating an application replaces the previous application with the new one downloaded by the user. During this process, iTunes installs the updated application in a new application directory. It then moves the user’s data files from the old installation over to the new application directory before deleting the old installation. Files in the following directories are guaranteed to be preserved during the update process:

  • <Application_Home>/Documents
  • <Application_Home>/Library/Preferences

Although files in other user directories may also be moved over, you should not rely on
them being present.after an update.

Keychain Data

A keychain is a secure, encrypted container for passwords and other secrets. The keychain data for an application is stored outside of the application sandbox. If an application is uninstalled, that data is automatically removed. When the user backs up application data using iTunes, the keychain data is also backed up. However, it can only be restored to the device from which the backup was made. An upgrade of an application does not affect its keychain data.

Getting Paths to Application Directories

At various levels of the system, there are programmatic ways to obtain file-system paths to the directory locations of an application’s sandbox. However, the preferred way to retrieve these paths is with the Cocoa programming interfaces. The NS Home Directory function (in the Foundation framework) returns the path to the top-level home directory—that is, the directory containing the application, Documents, Library, and tmp directories. In addition to that function, you can also use the NS Search Path For Directories InDomains and NS Temporary Directory functions to get exact paths to your Documents, Caches, and tmp directories.

Both the NS Home Directory and NS Temporary Directory functions return the properly formatted path information in an NSString object. You can use the path-related methods of NSString to modify the path information or create new path strings. For example, upon retrieving the temporary directory path, you could append a file name and use the resulting string to create a file with the given name in the temporary directory.

The NS SearchPath For Directories InDomains function of the Foundation framework lets you obtain the full path to several application-related directories. To use this function in iPhone OS, specify an appropriate search path constant for the first parameter and NS User Domain Mask for the second parameter.

Table lists several of the most commonly used constants and the directories they return.

Commonly used search path constants

Commonly used search path constants

Because the NSSearchPathForDirectoriesInDomains function was designed originally for Mac OS X, where multiple such directories could exist, it returns an array of paths rather than a single path. In iPhone OS, the resulting array should contain t he single path to the desired directory. Listing shows a typical use of this function.

Getting a file-system path to the application’s Documents/ directory

You can call NSSearchPathForDirectoriesInDomains using a domain-mask parameter other than NS User Domain Mask or a directory constant other than those in Table, but the application will be unable to write to any of the returned directory locations. For example, if you specify NS Application Directory as the directory parameter and NS System Domain Mask as the domain-mask parameter, you get the path /Applications returned (on the device), but your application cannot write any files to this location.

Another consideration to keep in mind is the difference in directory locations between platforms. The paths returned by NS Search Path For Directories InDomains, NS Home Directory, NS Temporary Directory, and similar functions differ depending on whether you’re running your application on the device or on the Simulator. For example, take the function call shown in Listing. On the device, the returned path (documentsDirectory) is similar to the following:

However, on the Simulator, the returned path takes the following form:

To read and write user preferences, use the NS User Defaults class or the CF Preferences API. These interfaces eliminate the need for you to construct a path to the Library/Preferences/ directory and read and write preference files directly. For more information on using these interfaces, see “Adding the SettingsBundle”

If your application contains sound, image, or other resources in the application bundle, you should use the NSBundle class or CF BundleRef opaque type to load those resources. Bundles have an inherent knowledge of where resources live inside the application. In addition, bundles are aware of the user’s language preferences and are able to choose localized resources over default resources automatically. For more information on bundles, see “The Application Bundle”

Reading and Writing File Data

The iPhone OS provides several ways to read, write, and manage files.

Foundation framework:

  • If you can represent your application’s data as a property list, convert the property list to anNSData object using the NSPropertyListSerialization API. You can then write the data object to disk using the methods of the NSData class.
  • If your application’s model objects adopt the NSCoding protocol, you can archive a graph of these model objects using the NS Keyed Archiver class, and especially its archived Data With Root Object method.
  • The NS File Handle class in Foundation framework provides random access to the contents of a file.
  • The NS File Manager class in Foundation framework provides methods to create and manipulate files in the file system.
  • Core OS calls:

  • Calls such as fopen, fread, and fwrite also let you read and write file data either sequentially or via random access.
  • The mmap and munmap calls provide an efficient way to load large files into memory and access their contents.

The following sections show examples of how to use some of the higher-level techniques for reading and writing files.

Reading and Writing Property List Data

A property list is a form of data representation that encapsulates several Foundation (and Core Foundation) data types, including dictionaries, arrays, strings, dates, binary data, and numerical and Boolean values.Property lists are commonly used to store structured configuration data. For example, the Info.plist file found in every Cocoa and iPhone applications is a property list that stores configuration information about the application itself. You can use property lists yourself to store additional information, such as the state of your application when it quits.

In code, you typically construct a property list starting with either a dictionary or array as a container object. You then add other property-list objects, including (possibly) other dictionaries and arrays. The keys of dictionaries must be string objects. The values for those keys are instances of NSDictionary, NSArray, NSString, NSDate, NSData, and NSNumber.

For an application whose data can be represented by a property-list object (such as an NS Dictionary object), you could write that property list to disk using a method

This method serializes the property list object into an NSData object, then calls the write Application Data: toFile: method (the implementation for which is shown in Listing to write that data to disk.

Converting a property-list object to an NSData object and writing it to storage

When writing property list files in iPhone OS, it is important to store your files in binary format. You do this by specifying the NS Property List Binary Format_v1_0 key in the format parameter of the data From Property List: format:error Description: method. The binary property-list format is much more compact than the other format options, which are text based. This compactness not only minimizes the amount of space taken up on the user’s device, it also improves the time it takes to read and write the property list

Listing shows the corresponding code for loading a property-list file from disk and reconstituting the objects in that property list.

Reading a property-list object from the application’s Documents directory

- (id)applicationPlistFromFile:(NSString *)fileName { NSData *retData; NSString *error; id retPlist; NSPropertyListFormat format; retData = [self applicationDataFromFile:fileName]; if (!retData) { NSLog(@"Data file not returned."); return nil; } retPlist = [NSPropertyListSerialization propertyListFromData:retData mutabilityOption: NSPropertyListImmutable format:&format errorDescription:&error]; if (!retPlist){ NSLog(@"Plist not returned, error: %@", error); } return retPlist; }

For more on property lists and the NS Property List Serialization class, see Property List programming Guide.

Using Archivers to Read and Write Data

An archiver converts an arbitrary collection of objects into a stream of bytes. Although this may sound similar to the process employed by the NS Property List Serialization class, there is an important difference. A property-list serializer can convert only a limited set of (mostly scalar) data types. Archivers can convert arbitrary Objective-C objects, scalar types, arrays, structures, strings, and more.

The key to the archiving process is in the target objects themselves. The objects manipulated by an archiver must conform to the NS Coding protocol, which defines the interface for reading and writing the object’s state. When an archiver encodes a set of objects, it sends an encode With Coder: message to each one, which the object then uses to write out its critical state information to the corresponding archive. The unarchiving process reverses the flow of information. During unarchiving, each object receives an init With Coder: message, which it uses to initialize itself with the state information currently in the archive. Upon completion of the unarchiving process, the stream of bytes is reconstituted into a new set of objects that have the same state as the ones written to the archive previously.

The Foundation framework supports two kinds of archivers— sequential and keyed. Keyed archivers are more flexible and are recommended for use in your application. The following example shows how to archive a graph of objects using a keyed archiver. The representation method of the _myDataSource object returns a single object (possibly an array or dictionary) that points to all of the objects to be included in the archive. The data object is then written to a file whose path is specified by the myFilePath variable.

To load the contents of an archive from disk, you simply reverse the process. After loading the data from disk, you use the NSKeyedUnarchiver class and its unarchiveObjectWithData: class method to get back the model-object graph. For example, to unarchive the data from the previous example, you could use the following code:

For more information on how to use archivers and how to make your objects support the NSCoding protocol, see Archives and Serializations Programming Guide for Cocoa.

Writing Data to Your Documents Directory

After you have an NSData object encapsulating the application data (either as an archive or a serialized property list), you can call the method shown in Listing to write that data to the application Documents directory.

ListingWriting data to the application’s Documents directory

Reading Data from the Documents Directory

To read a file from your application’s Documents directory, construct the path for the file name and use the desired method to read the file contents into memory. For relatively small files—that is, files less than a few memory pages in size—you could use the code in Listing to obtain a data object for the file contents.This example constructs a full path to the file in the Documents directory, creates a data object from it, and then returns that object.

Reading data from the application’s Documents directory

For files that would require multiple memory pages to hold in memory, you should avoid loading the entire file all at once. This is especially important if you plan to use only part of the file. For larger files, you should consider mapping the file into memory using either the mmap function or the init With Contents Of Mapped File: method of NSData.

Choosing when to map files versus load them directly is up to you. It is relatively safe to load a file entirely into memory if it requires only a few (3-4) memory pages. If your file requires several dozen or a hundred pages, however, you would probably find it more efficient to map the file into memory. As with any such determination, though, you should measure your application’s performance and determine how long it takes to load the file and allocate the necessary memory.

File Access Guidelines

When creating files or writing out file data, keep the following guidelines in mind:

  • Minimize the amount of data you write to the disk. File operations are relatively slow and involve writing to the Flash disk, which has a limited lifespan. Some specific tips to help you minimize file-related operations include:
  • Write only the portions of the file that changed, but aggregate changes when you can. Avoid writing out the entire file just to change a few bytes.
  • When defining your file format, group frequently modified content together so as to minimize the overall number of blocks that need to be written to disk each time.
  • If your data consists of structured content that is randomly accessed, store it in a Core Data persistent store or a SQLite database. This is especially important if the amount of data you are manipulating could grow to be more than a few megabytes in size.
  • Avoid writing cache files to disk. The only exception to this rule is when your application quits and you need to write state information that can be used to put your application back into the same state when it is next launched.

Saving State Information

When the user presses the Home button, iPhone OS quits your application and returns to the Home screen. Similarly, if your application opens a URI whose scheme is handled by a different application, iPhone OS quits your application and opens the URI in the other application. In other words, any action that would cause your application to suspend or go to the background in Mac OS X causes your application to quit in iPhone OS. Because these actions happen regularly on mobile devices, your application must change the way it manages volatile data and application state.

Unlike most desktop applications, where the user manually chooses when to save files to disk, your application should save changes automatically at key points in your workflow. Exactly when you save data is up to you, but there are two potential options. Either you can save each change immediately as the user makes it, or you can batch changes on the same page together and save them when the page is dismissed, a new page is displayed, or the application quits. Under no circumstances should you let the user navigate to a new page of content without saving the data on the previous page.

When your application is asked to quit, you should save the current state of your application to a temporary cache file or to the preferences database. The next time the user launches your application, use that information to restore your application to its previous state. The state information you save should be as minimal as possible but still let you accurately restore your application to an appropriate point. You do not have to display the exact same screen the user was manipulating previously if doing so would not make sense. For example, if a user edits a contact and then leaves the Phone application, upon returning, the Phone application displays the top-level list of contacts, rather than the editing screen for the contact.

Case Sensitivity

The file system for iPhone OS–based devices is case sensitive. Whenever you work with filenames, you should be sure that the case matches exactly or your code may be unable to open or access the file.

All rights reserved © 2020 Wisdom IT Services India Pvt. Ltd Protection Status