File and Data Management
Files on the phone OS system and user media data and personal files share the space on flash. For security purposes, your application is stored in its own directory and can only read and write the directory.
Common Directories
For security purposes, applications can only write their own data and preference settings to specific locations.
When an application is installed on a device, the system creates a home directory for it.
<Application_Home>/
AppName. App this isPackageDirectory, including the application itself.
<Application_home>/Documents/You should write all application data files to this directory. This directory is used to store user data or other information that should be regularly backed up. ITunes backs up the contents of this directory.
<Application_home>/Library/Preferences
This directory contains the preference setting file of the application. ITunes backs up the contents of this directory.
<Application_home>/Library/Caches
This directory is used to store application-specific support files and save the information required when the application starts again. ITunes does not back up the contents of this directory.
<Application_home>/tmp/
This directory is used to store temporary files and save the information that is not required when the application starts up again. ITunes does not back up the contents of this directory.
Backup and recovery
You do not need to make any preparations for backup and recovery operations in the application. In iPhone OS 2.2 and later versions, when a device is connected to a computer and synced, iTunes will incrementally back up all files except the following directories:
Although iTunes doesPackageThis operation is not performed during each synchronization. Applications purchased through App Store on the device are backed up during the next synchronization between the device and iTunes. In subsequent synchronization operations, the application does not back up unless the application package itself changes (for example, because the application is updated ).
<Application_home>/Documents
The directory should be used to store user data files or files that are not easily recreated in applications. Files storing temporary data should be placed inApplication home/tmp
Directory, and delete it when not needed. If your application needs to create data files for next startup, put those filesApplication home/Library/Caches
Directory.
Files saved during application update
During the update process, iTunes ensures that files in the following directories are retained:
Although files in other user directories may also be transferred, you should not assume that the file still exists after the update.
Keychain data
Keychain is a secure and encrypted container used to save passwords and other confidential information. The keychain data of the application is stored outside the application sandbox. If the application is uninstalled, the data is automatically deleted. When you back up application data through iTunes, the keychain data is also backed up. However, the keychain data can only be restored to the device that was previously backed up. Application updates do not affect its keychain data.
Obtain the application directory path
In the Foundation frameworkNSSearchPathForDirectoriesInDomains
Function is used to obtain the full path of several application-related directories. When using this function on iPhone OS, the first parameter specifies the correct search path constant, and the second parameter usesNSUserDomainMask
Constant. Table 6-2 lists most common constants and their returned directories.
Table 6-2Common search path Constants
Constant |
Directory |
NSDocumentDirectory
|
<Application_Home>/Documents |
NSCachesDirectory
|
<Application_Home>/Library/Caches |
NSApplicationSupportDirectory
|
<Application_Home>/Library/Application Support |
BecauseNSSearchPathForDirectoriesInDomains
The function was initially designed for Mac OS x, and Mac OS X may have multiple such directories. Therefore, its return value is a path array instead of a single path. On iPhone OS, the result array should only contain the path of a given directory. The program list 6-1 shows the typical usage of this function.
Program list 6-1Obtain the point to ApplicationDocuments
Directory file system path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); |
NSString *documentsDirectory = [paths objectAtIndex:0]; |
Before callingNSSearchPathForDirectoriesInDomains
You can useNSUserDomainMask
Other domain mask parameters, or other directory constants outside of Table 6-2, but the application cannot write data to the returned directory. For example, if you specifyNSApplicationDirectory
As a DIRECTORY parameter, specifyNSSystemDomainMask
As the domain mask parameter, you can return (on the device)/Applications
Path. However, your application cannot write any files to this location.
UseNSUserDefaults
Class orCFPreferences
API. These interfaces prevent you from constructingLibrary/Preferences/
Directory path and direct read/write preference file.
If the application package contains sound, image, or other resources, useNSBundle
Class orCFBundleRef
Encapsulation type to load those resources. The package knows where the internal resources of the application should be located. In addition, it also knows the user's language preferences and can automatically select localized resources.
File data read/write
The iPhone OS provides the following methods to read, write, and manage files:
FoundationFramework:
If you can represent application data asAttribute list, You can useNSPropertyListSerialization
API to convert the attribute list toNSData
Object, and thenNSData
Class to write data objects to the disk.
IfModel objectAdoptedNSCoding
Protocol, you can useNSKeyedArchiver
Class, especially itsarchivedDataWithRootObject:
Method to archive a model object graph.
In the Foundation frameworkNSFileHandle
Class provides a method to randomly access the file content.
In the Foundation frameworkNSFileManager
Class to create and operate files in the file system.
Core OS call:
Suchfopen
,fread
, Andfwrite
These calls can be used to perform sequential or random read/write operations on files.
mmap
Andmunmap
Calling is an effective way to load a large file into the memory and access its content.
Read/write attribute list data
In code, the construction of the attribute list usually starts from constructing a dictionary or array and using it as a container object, and then adding other attribute list objects to the container, (possibly) contains other dictionaries and arrays. The dictionary key must be a string object, and the key value isNSDictionary
,NSArray
,NSString
,NSDate
,NSData
, AndNSNumber
Class.
For applications that can represent data as attribute list objects (for exampleNSDictionary
Object), you can use the method shown in the program list 6-2 to write the attribute list to the disk. This method serializes the attribute listNSData
Object, and then callwriteApplicationData:toFile:
Method (its implementation is shown in program list 6-4) to write data to the disk.
Procedure List 6-2Convert an attribute list objectNSData
Object and write it to storage
- (BOOL)writeApplicationPlist:(id)plist toFile:(NSString *)fileName { |
NSString *error; |
NSData *pData = [NSPropertyListSerialization dataFromPropertyList:plist format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]; |
if (!pData) { |
NSLog(@"%@", error); |
return NO; |
} |
return ([self writeApplicationData:pData toFile:(NSString *)fileName]); |
} |
It is important to store attribute list files in binary format on the iPhone OS system. During encodingdataFromPropertyList:format:errorDescription:
MethodFormatParameter specifiedNSPropertyListBinaryFormat_v1_0
Value. The binary format is much more compact than other text-based formats. This compact not only minimizes the space occupied by the attribute list on the user's device, but also reduces the read/write attribute list time.
The code in Listing 6-3 shows how to load the attribute list from the disk and regenerate the objects in the attribute list.
Program list 6-3From the application'sDocuments
Directory read attribute list object
- (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; |
} |
Use an archive to read and write data
ArchiveIs used to convert any object set into byte streams. It sounds likeNSPropertyListSerialization
But there is an important difference between them. Attribute list serialization can only convert the Data Type of a finite set (most of which are quantitative ), the archive can convert any objective-C object, quantity type, array, structure, string, and more types.
The key to the archiving process is the target object itself. Objects operated by the archive must followNSCoding
ProtocolThis Protocol defines the interface for reading and writing object states. When you encode a group of objects, the archive will sendencodeWithCoder:
Message. The target object writes its key state information to the corresponding file in this method. The information flow in the archive process is the opposite. During the archive process, each object receivesinitWithCoder:
Message, used to read the current status information from the file and initialize it based on the information. After the archive process is completed, the byte stream is re-formed into a group of new objects in the same state as before when the file is written.
The foundation framework supports two archivers: sequential archiving and key-based archiving. Key-based archivers are more flexible and are recommended for application development. The following example shows how to archive an object graph with a key-based archive._myDataSource
Objectrepresentation
Method to return a separate object (may be an array or dictionary), pointing to all objects to be included in the file, then the data object is writtenmyFilePath
Variable specified path file.
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[_myDataSource representation]]; |
[data writeToFile:myFilePath atomically:YES]; |
Note:You can alsoNSKeyedArchiver
Object sendingarchiveRootObject:toFile:
To create an archive and write the archive to the storage in one step.
You can simply load the file content on the disk through the opposite process. After loading the disk data, you canNSKeyedUnarchiver
Class andunarchiveObjectWithData:
Class to retrieveModel objectGraph. For example, you can use the following code to parse the data in the previous example:
NSData* data = [NSData dataWithContentsOfFile:myFilePath]; |
id rootObject = [NSKeyedUnarchiver unarchiveObjectWithData:data]; |
Write Data to the documents directory
Program list 6-4Write Data to the applicationDocuments
Directory
- (BOOL)writeApplicationData:(NSData *)data toFile:(NSString *)fileName { |
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); |
NSString *documentsDirectory = [paths objectAtIndex:0]; |
if (!documentsDirectory) { |
NSLog(@"Documents directory not found!"); |
return NO; |
} |
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName]; |
return ([data writeToFile:appFile atomically:YES]); |
} |
Read data from the documents directory
To read a file from the program's Documents directory, you must first construct a path based on the file name, and then read the file content into the memory as expected. For a relatively small file, that is, a file with a size smaller than several memory pages, you can use the code in Listing 6-5 to obtain the file content. The code isDocuments
Create a full path for the files in the directory, create a data object for the path, and then return.
Program list 6-5From the application'sDocuments
Directory read data
- (NSData *)applicationDataFromFile:(NSString *)fileName { |
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); |
NSString *documentsDirectory = [paths objectAtIndex:0]; |
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName]; |
NSData *myData = [[[NSData alloc] initWithContentsOfFile:appFile] autorelease]; |
return myData; |
} |
When loading files that require multiple memory pages, you should avoid loading the entire file at one time. This is especially important if you only plan to use some files. For large files, you should consider usingmmap
Function orNSData
OfinitWithContentsOfMappedFile:
Method To map files to memory.
Guidelines for File Access
When creating a file or writing file data, remember the following guidelines:
Minimize the amount of data written to the disk. The file operation speed is relatively slow, and the Flash disk write operation is involved, there is a certain life limit. The following tips help you minimize file-related operations:
Write only the changed part of the file, but accumulate the changes as much as possible to avoid writing the entire file when only a few bytes change.
When defining the file format, put frequently changed content together to minimize the total number of data blocks to be written to the disk each time.
If your Data is structured content that requires random access, you can store them in the Core Data persistent warehouse or SQLite database. This is especially important if the amount of data you process may increase to more than a few megabytes.
Avoid writing cached files to disks. The only exception to this principle is that when the application exits, you need to write some status information so that the program can return to the previous status at the next startup.
Network
Both the cellular network and the Wi-Fi wireless network are designed to power off when there is no data transmission activity.
Compared with regular transmission of a small amount of data, it is better to transmit all data at a time or for a long time interval, but it is better to transmit a large amount of data at a time.
Use Wi-Fi
If your application accesses the network through Wi-Fi wireless signals, you must notify the system of this fact, that is, in the application'sInfo.plist
File containsUIRequiresPersistentWiFi
Key. This key is included so that the system knows that the Network Selection box should pop up when detecting the active Wi-Fi hotspot and that the system should not try to disable the Wi-Fi hardware when your application is running.
To prevent Wi-Fi hardware from consuming too much power, the iPhone OS has a built-in timer. If no application passes through within 30 minutesUIRequiresPersistentWiFi
If the key request uses Wi-Fi, the hardware is completely disabled. If a user starts an application containing the key, the iPhone OS will effectively disable the timer during the life cycle of the application. However, once the program exits, the system will re-enable the timer.
Note:Even ifUIRequiresPersistentWiFi
The key value istrue
It does not work when the device is idle (that is, in the screen lock status. In that case, the application is considered inactive, although it may still work at some level, but there is no Wi-Fi connection.
Flight mode warning
When the application starts, if the device is in flight mode, the system may display a dialog box to notify the user. The notification dialog box is displayed only when all of the following conditions are met:
Application InformationAttribute list(Info.plist
) File InclusionUIRequiresPersistentWiFi
And the value of the key is set to true.
The device is in flight mode when the application starts.
After switching to flight mode, Wi-Fi on the device has not been manually activated.