This tutorial is the first I’m going to do in a series of tutorials dealing with data in our apps. The series will include different ways to bring data into our app as well as ways to save data from our app to use the next time the app is launched. I’m going to start with property lists or plists as they are often called.
We’ll be talking more about this in future tutorials, for now we are just going to create a very simple property list as an xml document, save some data to it, and then read that data back out of the plist the next time we run the app.
Property lists are a convenient way to access and store small amounts of data. You cannot store custom data objects in a plist, only standard types such as String, Integer etc … as well as collections of standard types. Plists most commonly stored in XML format though they can also be stored in binary form. Property lists are very user friendly because there are methods already in place to store an object or array of objects as a plist xml document and to then other methods to read a plist xml document and convert it back into an object or dictionary etc … What this means is you don’t have to do the parsing of the xml yourself.
We’ll be talking more about this in future tutorials, for now we are just going to create a very simple property list as an xml document, save some data to it, and then read that data back out of the plist the next time we run the app.
For more information on plists refer to Apple’s documentation.
1.) Create a new View-based Application named PlistTutorial.
2.) Right click on Resources and select Add > New File, under Mac OS X select Other and then Empty File and name it Data.plist.
3.) Double click on Data.plist in Xcode to open it up there and add a String “Name”, and an Array “Phones” which has three items. You can add the items by clicking on the little symbol
on the far right edge of the line that says root.
Edit the fields by clicking in them and then typing.
After adding the Name String select Root again to display the add icon and repeat the process to add the Array.
Then click the little arrow next to Phone and it will display the add icon so you can add items to the array.
It should look something like this when you are done. You can change the order of the elements just by dragging them.
4.) Open up PropertyListExampleViewController.h and add six variables to it and two IBActions. It should be fairly obvious what these are so I won’t go into them in detail. The textFieldReturn method will be used to dismiss the keyboard when the return key is pressed, saveData will get called from a UIButton in the user interface.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #import "UIKit/UIKit.h" @interface PlistTutorialViewController : UIViewController { IBOutlet UITextField *nameEntered; IBOutlet UITextField *homePhone; IBOutlet UITextField *workPhone; IBOutlet UITextField *cellPhone; NSString *personName; NSMutableArray *phoneNumbers; } @property (nonatomic, retain) UITextField *nameEntered; @property (nonatomic, retain) UITextField *homePhone; @property (nonatomic, retain) UITextField *workPhone; @property (nonatomic, retain) UITextField *cellPhone; @property (nonatomic, retain) NSString *personName; @property (nonatomic, retain) NSMutableArray *phoneNumbers; - (IBAction) saveData; - (IBAction) textFieldReturn:(id)textField; @end |
Then open up the implementation file and synthesize those variables.
1 2 3 4 5 6 7 | #import "PlistTutorialViewController.h" @implementation PlistTutorialViewController @synthesize personName; @synthesize phoneNumbers; @synthesize nameEntered, homePhone, workPhone, cellPhone; |
5.) Create the user interface, and link up the user interface elements to appropriate IBOutlets. If you need help with this check out one of the tutorials on building a user interface. You just need to make it look something like this.
You need to link each of the UITextField’s to the IBAction textFieldReturn as well and select Did End On Exit. This will allow us to dismiss the keyboard when we press the return key.
6.) Open up PropertyListExampleViewController.m. We’re going to retrieve the Data.plist file in the viewDidLoad method, and set the textFields in our user interface to the values retrieved from our Data.plist. I’m going to let the comments describe what is going on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | - (void)viewDidLoad { [ super viewDidLoad]; // Data.plist code // get paths from root direcory NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); // get documents path NSString *documentsPath = [paths objectAtIndex:0]; // get the path to our Data/plist file NSString *plistPath = [documentsPath stringByAppendingPathComponent:@ "Data.plist" ]; // check to see if Data.plist exists in documents if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) { // if not in documents, get property list from main bundle plistPath = [[NSBundle mainBundle] pathForResource:@ "Data" ofType:@ "plist" ]; } // read property list into memory as an NSData object NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath]; NSString *errorDesc = nil; NSPropertyListFormat format; // convert static property liost into dictionary object NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc]; if (!temp) { NSLog(@ "Error reading plist: %@, format: %d" , errorDesc, format); } // assign values self.personName = [temp objectForKey:@ "Name" ]; self.phoneNumbers = [NSMutableArray arrayWithArray:[temp objectForKey:@ "Phones" ]]; // display values nameEntered.text = personName; homePhone.text = [phoneNumbers objectAtIndex:0]; workPhone.text = [phoneNumbers objectAtIndex:1]; cellPhone.text = [phoneNumbers objectAtIndex:2]; } |
7.) Save everything, Build and Run and at this point and you can see that the values in Data.plist are being read and populating the UITextFields.
8.) Now we’ll write the Data.plist file with values taken from our UI. Implement the method saveData in our view controller implementation file and write the values in the UITextFields back to our Data.plist file. Again I’ll let the comments explain what is going on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | - (IBAction) saveData { // get paths from root direcory NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); // get documents path NSString *documentsPath = [paths objectAtIndex:0]; // get the path to our Data/plist file NSString *plistPath = [documentsPath stringByAppendingPathComponent:@ "Data.plist" ]; // set the variables to the values in the text fields self.personName = nameEntered.text; self.phoneNumbers = [[NSMutableArray alloc] initWithCapacity:3]; [phoneNumbers addObject:homePhone.text]; [phoneNumbers addObject:workPhone.text]; [phoneNumbers addObject:cellPhone.text]; // create dictionary with values in UITextFields NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: personName, phoneNumbers, nil] forKeys:[NSArray arrayWithObjects: @ "Name" , @ "Phones" , nil]]; NSString *error = nil; // create NSData from dictionary NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error]; // check is plistData exists if (plistData) { // write plistData to our Data.plist file [plistData writeToFile:plistPath atomically:YES]; } else { NSLog(@ "Error in saveData: %@" , error); [error release]; } } |
9.) Now implement the textFieldReturn IBAction in our view controller implementation method so that we can dismiss the keyboard.
1 2 3 4 5 | // we use this to dismiss the keyboard when the return key is pressed - (IBAction) textFieldReturn:(id)textField { [textField resignFirstResponder]; } |
10.) Save everything, Build and Run and test it out. When you enter new data into the text fields and click the save data button, it should get saved to the Data.plist file and then be read in the next time the app is loaded.
0 comments:
Post a Comment