IOS 7 Data Persistence using Archiving

From Techotopia
Jump to: navigation, search
PreviousTable of ContentsNext
Synchronizing iOS 7 Key-Value Data using iCloudiOS 7 Database Implementation using SQLite


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


In the previous chapters of this book we have looked at some basic file and directory handling operations which can be performed within an iOS 7 application. In the chapter entitled Working with Files on iOS 7 we looked at creating files and reading and writing data from within an iOS application before looking at iCloud based storage in subsequent chapters. In this chapter we will look at another form of data persistence on iOS 7 using a more object oriented approach known as archiving.


Contents


An Overview of Archiving

iOS applications are inherently object oriented in so much as they are developed using Objective-C and consist of any number of objects designed to work together to provide the required functionality. As such, it is highly likely that any data created or used within an application will be held in memory encapsulated in an object. It is also equally likely that the data encapsulated in an object may need to be saved to the device’s file system so that it can be restored on future invocations of the application. One approach might be to write code that extracts each data element from an object and writes it to a file. Similarly, code would need to be written to read the data from the file, create an instance of the original object and then assign the data to that object accordingly. Whilst this can be achieved, it can quickly become complex and time consuming to implement.

An alternative is to use a mechanism called archiving. Archiving involves encoding objects into a format that is written to a file. Data may subsequently be decoded (or unarchived) and used to automatically rebuild the object. This concept is somewhat analogous to serialization as supported by languages such as Java.

A number of approaches to archiving are supported by the Foundation Framework. Arguably the most flexible option is that provided by the NSKeyedArchiver class. This class provides the ability to encode an object into the form of a binary property list that is written to file and may subsequently be decoded to recreate the object using the NSKeyedUnarchiver class.

An alternative option is to use the writeToFile:anatomically method available with a subset Foundation class. This mechanism writes the object data to file in the form of an XML property list file. This approach, however, is limited to NSArray, NSData, NSDate, NSDictionary, NSNumber and NSString based objects.

In the remainder of this chapter we will work through an example of archiving using the NSKeyedArchiver and NSKeyedUnarchiver classes.

The Archiving Example Application

The end product of this chapter is an application that prompts the user for a name, address and phone number. Once this data has been entered, pressing a button causes the contact data to be stored in an array object which is then archived to a binary property file. On a subsequent reload of the application this data is unarchived and used to recreate the array object. The restored data is then extracted from the array object and presented to the user.

Begin by launching Xcode and create a new iPhone or iPad project named Archive using the Single View Application template. Once the main Xcode project window appears populated with the template files, it is time to start developing the application.


Designing the User Interface

The user interface for our application is going to consist of three UILabels, three UITextFields and a single UIButton. Select Main.storyboard in the Xcode project navigator and display the Object Library panel (View -> Utilities -> Show Object Library) if it is not already visible. Drag, drop, resize, position and configure objects on the View window canvas until your design approximates that illustrated in Figure 38-1:

The user interface for an iOS 7 Archive example app

Figure 38-1


The next step is to establish the connections to our action and outlets. Select the top most text field object in the view canvas, display the Assistant Editor panel and verify that the editor is displaying the contents of the ArchiveViewController.h file. Ctrl-click on the text field object again and drag to a position just below the @interface line in the Assistant Editor. Release the line and in the resulting connection dialog establish an outlet connection named name.

Repeat the above steps to establish outlet connections for the remaining text fields to properties named address and phone respectively.

Ctrl-click on the button object and drag the line to the area immediately beneath the newly created outlets in the Assistant Editor panel. Release the line and, within the resulting connection dialog, establish an Action method on the Touch Up Inside event configured to call a method named saveData.

Select the ArchiveViewController.h file and add an additional NSString property to store a reference to the path to the archive data file:

#import <UIKit/UIKit.h>

@interface ArchiveViewController : UIViewController 

@property (strong, nonatomic) IBOutlet UITextField *name;
@property (strong, nonatomic) IBOutlet UITextField *address;
@property (strong, nonatomic) IBOutlet UITextField *phone;
@property (strong, nonatomic) NSString *dataFilePath;
- (IBAction) saveData;
@end

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Checking for the Existence of the Archive File on Startup

Each time the application is launched by the user, the code will need to identify whether the archive data file exists from a previous session. In the event that it does exist, the application will need to read the contents to recreate the original array object from which the archive was created. Using this newly recreated array object, the array elements will then be extracted and used to populate the name, address and phone text fields.

The traditional location for placing such initialization code is in the viewDidLoad method of the view controller class. Within the project window, therefore, select the ArchiveViewController.m file and scroll down the contents of this file until you reach the viewDidLoad method. Having located the method, modify it as outlined in the following code fragment:

- (void)viewDidLoad {
 [super viewDidLoad];
 NSFileManager *filemgr;
 NSString *docsDir;
 NSArray *dirPaths;

 filemgr = [NSFileManager defaultManager];

 // Get the documents directory
 dirPaths = NSSearchPathForDirectoriesInDomains(
   NSDocumentDirectory, NSUserDomainMask, YES);

 docsDir = dirPaths[0];

 // Build the path to the data file
 _dataFilePath = [[NSString alloc] initWithString: [docsDir
        stringByAppendingPathComponent: @"data.archive"]];

 // Check if the file already exists
 if ([filemgr fileExistsAtPath: _dataFilePath])
 {
         NSMutableArray *dataArray;

         dataArray = [NSKeyedUnarchiver
          unarchiveObjectWithFile: _dataFilePath];

         _name.text = dataArray[0];
         _address.text = dataArray[1];
         _phone.text = dataArray[2];
 }
}

Within this method a number of variables are declared before creating an instance of the NSFileManager class.

A call is then made to the NSSearchPathForDirectoriesInDomains function and the path to the application’s Documents directory extracted from the returned array object. This path is then used to construct the full pathname of the archive data file, which in turn is stored in the dataFilePath instance variable we previously added to the view controller class interface file.

Having identified the path to the archive data file, the file manager object is used to check for the existence of the file. If it exists, the file is “unarchived” into a new array object using the unarchiveObjectWithFile method of the NSKeyedUnarchiver class. The data is then extracted from the array and displayed in the corresponding text fields.

With this code implemented, select the Run toolbar button to compile and execute the application in the simulator. Assuming no problems are encountered, the next step is to implement the action method. If problems are encountered, check the details reported by Xcode and correct any syntax errors that may have been introduced into the code. Once the app has launched successfully, exit from the iOS Simulator and return to the main Xcode project window.

Archiving Object Data in the Action Method

The Save button in the user interface design is connected to the saveData method of the view controller class. Edit the ArchiveViewController.m file and modify the template action method as follows:

- (void) saveData:(id)sender
{
     NSMutableArray *contactArray;

     contactArray = [[NSMutableArray alloc] init];
     [contactArray addObject:_name.text];
     [contactArray addObject:_address.text];
     [contactArray addObject:_phone.text];
     [NSKeyedArchiver archiveRootObject: 
       contactArray toFile:_dataFilePath];
}

When triggered, this method creates a new array and assigns the content of each text field to an element of that array. The array object is then archived to the predetermined data file using the archiveRootObject method of the NSKeyedArchiver class. The instance data of the array object is now saved to the archive ready to be loaded next time the application is executed.

Testing the Application

Save the code changes and build and run the application on a device or in the simulator environment. Enter a name, address and phone number into the respective text fields and press the save button. Stop the application by clicking the Stop button located in the Xcode toolbar and then relaunch the application by clicking Run. The application should re-appear with the text fields primed with the contact information saved during the previous session:


An iOS 7 data archiving example running

Figure 38-2


Summary

Whilst data can be written to files on an iOS device using a variety of mechanisms, archiving provides the ability to save the instance data of an object to file at a particular point and then restore the object to that state at any time in the future. This provides an object-oriented approach to data persistence on iOS based applications.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
Synchronizing iOS 7 Key-Value Data using iCloudiOS 7 Database Implementation using SQLite