We are going to expand on what we did in Part 1 and display an image of the gadget when the name is clicked. So now we have two types of data, a list of names of the gadgets and their corresponding images.
Using Property Lists to Store Data.
As a best practice, We should keep our data separate from your controller and view code. Most of you will know this as the Model/View/Controller paradigm where Model here represents the data store and the access methods.
As our applications gets a little more complicated we will move our data out from where we are currently placing them in code and into a persistent data store called Property Lists, or plists for short. You can find out more information about plists here.
1. We will have 2 plists. One is simply an array of the gadget names, and the other is a dictionary with the name as key and a URL to an image as the value. The plists can be downloaded here.
Our Gadget Class
2. We will be creating a class called Gadget to hold the data for each gadget.
Right click on Classes and choose Add > New File. You will be presented with a New File dialog.
Select the Objective-C Class template.
Ensure that Subclass of NSObject is showing in the dropdown.
Cick Next
On the next page, name the file, Gadget. Ensure the Also Create "Gadget.h" is checked
Click Finish.
3. Now we will declare and implement our Gadget class. We are going to add 2 instance variables, name and imageURL. We are going to use the @property keyword to expose for synthesize later. We are also going to declare a method initGadget to initialise our objects. Open the Gadget.h in Classes folder and edit it as follows:
@interface Gadget : NSObject {
NSString *name;
NSString *imageURL;
}
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *imageURL;
-(id)initGadget:(NSString *)rName imageURL:(NSString *)rImageURL;
@end
4. Now to synthesize the variables and implement initGadget in Gadget.m:
@synthesize name, imageURL;
-(id)initGadget:(NSString *)rName imageURL:(NSString *)rImageURL{
self.name = rName;
self.imageURL = rImageURL;
return self;
}
Reading the Data
5. Next we are going to read the data from the property lists into Gadget objects and store them in the gadgets array. Previously we defined gadgets as NSArray. Change it now to NSMutableArray. Open RootViewController.m and import Gadget.h
Next in ViewDidLoad method we are going to read data from the plists:
NSArray *plistArray; NSString *path = [[NSBundle mainBundle] bundlePath]; NSString *finalPath = [path stringByAppendingPathComponent:@"gadget-names.plist"]; plistArray = [NSArray arrayWithContentsOfFile:finalPath]; NSDictionary *plistDict; path = [[NSBundle mainBundle] bundlePath]; finalPath = [path stringByAppendingPathComponent:@"gadgetDict.plist"]; plistDict = [NSDictionary dictionaryWithContentsOfFile:finalPath];
6. Now that we have read the data into an array and dictionary respectively we are going to create gadget object from them and add them to the gadgets array. Change the gadgets array type to MSMutableArray and do the following in ViewDidLoad:
gadgets = [[NSMutableArray alloc] init]; //initialise the gadgets array int gadgetMax = plistArray.count; int i; for(i = 0; i < gadgetMax;i++){ NSString *aName = [plistArray objectAtIndex:i]; NSString *aImageURL = [plistDict objectForKey:aName]; Gadget *gadget =[[Gadget alloc] initGadget:aName imageURL:aImageURL]; [gadgets addObject:gadget]; [gadget release]; }
Naturally this replaces how gadgets is populated compared to Part 1.
7. Next we need to modify cellForRowAtIndexPath:
// Configure the cell. Gadget *gadget = (Gadget *)[gadgets objectAtIndex:indexPath.row]; cell.textLabel.text=gadget.name; return cell;
We cast into a gadget object for ease of reference. Now run the app to confirm it is working as before.
Create a new ViewController
8. Next we are going to define a new ViewController class to display our gadgets' images. Right click on Classes and choose Add > New File. You will be presented with a New File dialog.
Choose the UIViewController subclass template.
Ensure the option, with XIB for user interface is checked.
On the next page give a name to the controller. Call it GadgetViewController
Ensure that the option to create a header file is ticked.
You now have a new view controller class and XIB file in your project.
Move the XIB file to the Resources folder.
9. Now we modify the GadgetViewController to have a variable of type UIImageView:
@interface GadgetViewController : UIViewController {
UIImageView *gadgetImage;
}
@property (nonatomic, retain) IBOutlet UIImageView *gadgetImage;
@end10. Next modify the GadgetViewController.m file to synthesize gadgetImage.
11. Now we modify the view GadgetViewController.xib. Drag a UIImageView to the View Window. Then connect up the UIImageView to our ivar gadgetImage.
12. Now let's get RootViewController ready to instantiate GadgetViewController. Remember to import the GadgetViewController.h so that RootViewController can do so. Under RootViewController ViewDidLoad method and add a title for the root view:
self.title = @"Gadgets";
Setting the title accomplishes two things. Firstly, it displays a title for the root view and secondly it enables a back button from the Gadget view.
13. Almost done. Scroll down to didSelectRowAtIndexPath and modify it like so:
GadgetViewController *detailViewController = [[GadgetViewController alloc]
initWithNibName:@"GadgetViewController" bundle:nil];
Gadget *gadget = (Gadget *)[gadgets objectAtIndex:indexPath.row];
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
detailViewController.title = gadget.name;
//receive image data from the URL and cast it into UIImage
NSData *imageData = [NSData dataWithContentsOfURL:
[NSURL URLWithString:[gadget imageURL]]];
UIImage *gadgetImage = [[UIImage alloc] initWithData:imageData cache:YES];
//to scale the image for AspectFit
detailViewController.gadgetImage.contentMode = UIViewContentModeScaleAspectFit;
detailViewController.gadgetImage.image = gadgetImage;
[detailViewController release];
Run your application. Click on a gadget name and you should be brought to a second view where an image of the gadget will be displayed. You may need to wait for a bit for the image to load from the Internet. All images are from Wikipedia. That's it!
No comments:
Post a Comment