MOBILE

iPhone Programming : Table-View-Based Applications - Building a Model

1/20/2011 3:50:05 PM
At this point, you should have a working UITableView. So far, you’ve implemented both the view and the controller parts of the MVC pattern. Now we’re going to return to Xcode and implement the model. This needs to be separate from the view and the view controller, since we want to decouple the way the data is stored from the way it is displayed as much as possible. This will increase the reusability of both the classes that handle the UI and the classes that store the data behind the scenes, allowing us to change how parts of the application work while affecting as little code as possible.

Right-click on the Classes folder in the Groups & Files pane and select AddNew File. When you see the New File window shown in Figure 1, make sure Cocoa Touch Class is selected on the left side of the screen. Next, select “Objective-C class,” make sure Subclass of NSObject is specified, and click on Next.

Figure 1. The New File window, which allows you to select the template Xcode will use to generate the new class interface and implementation file


You will then be asked for the filename of the new class. Type in City.m and click on Finish. Xcode will generate a pair of files, City.h and City.m, containing the template interface and the implementation of the new class, and will put them in the Classes folder. If you look at these files, you can see that since you specified that the class was a subclass of the base NSObject class, Xcode really hasn’t created a lot of code. It didn’t know what you wanted the object for, so you’re going to have to write some code.

Open the City.h file and add variables to hold the name of our city, a short descriptive paragraph, and an image. Declare these variables as properties.

#import <Foundation/Foundation.h>

@interface City : NSObject {
NSString *cityName;
NSString *cityDescription;
UIImage *cityPicture;
}

@property (nonatomic, retain) NSString *cityName;
@property (nonatomic, retain) NSString *cityDescription;
@property (nonatomic, retain) UIImage *cityPicture;

@end

I’m declaring the name and description as an NSString, and I’m declaring the variable used to hold the picture as a UIImage. UIImage is a fairly high-level class that can be directly displayed in a UIImageView that we can create inside Interface Builder.


Note:

I could have decided to use an NSMutableString rather than an NSString. An NSMutableString is a subclass of NSString that manages a mutable string, which is a string whose contents can be edited. Conversely, an NSString object manages an immutable string, which, once created, cannot be changed and can only be replaced. Using mutable strings here might give us a bit more flexibility later on, and if you decide you need it, you can always go back and change these definitions to mutable strings later. Changing from using an NSString to an NSMutableString is easy since mutable strings are a subclass and implement all of the methods provided by the NSString class. Going in the opposite direction is more difficult, unless you have not made use of the additional functionality offered by the mutable string class.


Open the City.m file and add code to @synthesize the cityName, cityDescription, and cityPicture accessor methods. After doing that, add a dealloc: method so that the variables will be released when the class is destroyed. Here’s what your City.m file should contain:

#import "City.h"

@implementation City

@synthesize cityName;
@synthesize cityDescription;
@synthesize cityPicture;

-(void) dealloc {
[cityName release];
[cityDescription release];
[cityPicture release];
[super dealloc];
}

@end

Because we made use of properties, our accessor methods will be generated for us automatically. So, we’re done now. Admittedly, this is just a fairly small class to hold some data, but it illustrates how useful properties will be for larger, more complex classes.

Let’s go back to the CityGuideDelegate class and prepopulate it with a few cities. You can put in longer descriptions if you want. If you’re just using it for personal testing, you could use text and images from Wikipedia. Later in the book I’ll show you how to retrieve data like this directly from the network, but for now we’ll hardcode (embed the data directly into the code; you normally will store your data outside the app) a few cities into the app delegate class and include the images inside the application itself rather than retrieving them from the network. Here’s what the CityGuideDelegate.h file should look like now (added lines are shown in bold):

#import <UIKit/UIKit.h>

@class RootController;

@interface CityGuideDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
RootController *viewController;
NSMutableArray *cities;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet RootController *viewController;
@property (nonatomic, retain) NSMutableArray *cities;

@end

In the application delegate interface file we declare our City class using the @class declaration, create an NSMutableArray to hold our list of cities, and declare this mutable array to be a property.

The changes to the application delegate implementation are slightly more extensive:

#import "CityGuideDelegate.h"
#import "RootController.h"
#import "City.h";

@implementation CityGuideDelegate

@synthesize window;
@synthesize viewController;
@synthesize cities;

- (void)applicationDidFinishLaunching:(UIApplication *)application {

City *london = [[City alloc] init];
london.cityName = @"London";
london.cityDescription =
@"The capital of the United Kingdom and England.";
london.cityPicture = [UIImage imageNamed:@"London.jpg"];
City *sanFrancisco = [[City alloc] init];
sanFrancisco.cityName = @"San Francisco";
sanFrancisco.cityDescription = @"The heart of the San Francisco Bay Area.";
sanFrancisco.cityPicture = [UIImage imageNamed:@"SanFrancisco.jpg"];
City *sydney = [[City alloc] init];
sydney.cityName = @"Sydney";
sydney.cityDescription = @"The largest city in Australia.";
sydney.cityPicture = [UIImage imageNamed:@"Sydney.jpg"];
City *madrid = [[City alloc] init];
madrid.cityName = @"Madrid";
madrid.cityDescription = @"The capital and largest city of Spain. ";
madrid.cityPicture = [UIImage imageNamed:@"Madrid.jpg"];
self.cities = [[NSMutableArray alloc]
initWithObjects:london, sanFrancisco, sydney, madrid, nil];

[london release];

[sanFrancisco release];
[sydney release];
[madrid release];

// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}

- (void)dealloc {
[viewController release];
[window release];
[cities release];

[super dealloc];
}

@end



Warning:

If you create a UIImage using the imageNamed: method as shown in this example, it is added to the default autorelease pool rather than the event loop autorelease pool. This means the memory associated with such images will be released only when the application terminates. If you use this method with many large images, you’ll find that your application may quickly run out of memory. Since these images are part of an autorelease pool, you’ll be unable to free the memory they use when the device’s operating system calls the didReceiveMemoryWarning: method in the application delegate when it runs short on memory. You should use the imageNamed: method sparingly, and generally only for small images.


1. Adding Images to Your Projects

As you can see, we retrieve the UIImage by name using the imageNamed: class method, but from where are we retrieving these images? The answer is, from somewhere inside the application itself. For testing purposes, I sorted through my image collection, found a representative image for each city (and then scaled and cropped the images to be the same size [1,000×750 pixels] and aspect ratio using my favorite image editing software), and copied them into the Xcode project. To do this yourself, drag and drop each image into the Resources folder in the Groups & Files pane. This brings up the copy file drop-down pane, as shown in Figure 2. If you want to copy the file into the project’s directory rather than create a link to wherever the file is stored, click on the relevant checkbox. If you do not copy the files to the project’s directory, they will still be collected in the application bundle file when Xcode compiles the application; however, if you later move or delete the file, Xcode will lose the reference to it and will no longer be able to access it. This is especially important when copying source code files. In general, I advocate always checking the box and copying the file into your project, unless you have a very good reason not to do so.


Note:

There are other ways to add a file to a project. You can also right-click on the Resources folder and select AddExisting Files to add a file to the project.


After you copy the downloaded images into the project, they become accessible from your code (see Figure 3). It’s generally advisable not to copy large images into the project. For example, if your binary gets too large you’ll have distribution problems. Among other problems, applications above a certain size cannot be downloaded directly from the App Store on the iPhone unless it is connected to the Internet via WiFi. Depending on the demographic you’re targeting, this may limit the market for your application. However, despite this, bundling images into your application is a good way to get easy access to small icons and logos that you may want to use in your project.

Figure 2. The drop down brought up when you drag and drop a file into the project


Figure 3. The downloaded images inside my Xcode project


Other  
  •  Mobile Application Security : The Apple iPhone - Push Notifications, Copy/Paste, and Other IPC
  •  Mobile Application Security : The Apple iPhone - Networking
  •  Windows Phone 7 Development : Handling Device Exceptions
  •  Registering a Windows Phone Device for Debugging
  •  Programming the Mobile Web : WebKit CSS Extensions (part 5) - Transformations
  •  Programming the Mobile Web : WebKit CSS Extensions (part 4) - Animations
  •  Programming the Mobile Web : WebKit CSS Extensions (part 3) - Transitions
  •  Programming the Mobile Web : WebKit CSS Extensions (part 2) - Reflection Effects & Masked Images
  •  Programming the Mobile Web : WebKit CSS Extensions (part 1) - WebKit Functions & Gradients
  •  Windows Phone 7 Development : Debugging Application Exceptions (part 2) - Debugging a Web Service Exception
  •  Windows Phone 7 Development : Debugging Application Exceptions (part 1) - Debugging Page Load Exceptions
  •  Programming the Mobile Web : JavaScript Libraries
  •  Programming the Mobile Web : Ajax Support
  •  Windows Phone 7 Development : Building a Phone Client to Access a Cloud Service (part 5) - Deploying the Service to Windows Azure
  •  Windows Phone 7 Development : Building a Phone Client to Access a Cloud Service (part 4) - Coding NotepadViewModel
  •  Windows Phone 7 Development : Building a Phone Client to Access a Cloud Service (part 3) - Coding the BoolToVisibilityConvert
  •  Windows Phone 7 Development : Building a Phone Client to Access a Cloud Service (part 2) - Coding MainPage
  •  Windows Phone 7 Development : Building a Phone Client to Access a Cloud Service (part 1) - Building the User Interface
  •  Building Android Apps : Detecting Browsers with WURFL
  •  Building Android Apps : Submitting Your App to the Android Market - Preparing a Release Version of Your App
  •  
    Top 10
    Programming Microsoft SQL Server 2005: Using the Data Mining Wizard and Data Mining Designer (part 6) - Validating and Comparing Mining Models
    Windows 7 : Putting Windows Explorer to Work for You
    iPhone Application Development : Using Switches, Segmented Controls, and Web Views (part 2)
    Sharepoint 2007: Upload a File - Upload a File from the Web Interface
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Algorithms for Compiler Design: CONTEXT-FREE GRAMMAR
    AJAX : Updating Progress
    Exchange Server 2007: Design and Deploy Disaster Recovery Settings - Use Dial-Tone Restores
    Animations in Silverlight
    Introducing Windows Mail
    Most View
    New Features of Windows Vista's Firewall
    Windows 7: Customizing Menus and the Control Panel (part 2) - Navigating and Customizing the Control Panel
    Exchange Server 2010 server roles (part 3) - Edge Transport Server role
    Programmatic Security (part 1) - The Permission Classes
    Defensive Database Programming with SQL Server : Client-side Error Handling
    IIS 7.0 : Setting Up Remote Logging by Using the IIS Manager
    Building Android Apps: Going Offline - Debugging
    Windows Azure and ASP.NET : Creating a Windows Azure Project
    Programming .NET Security : Digital Signatures Explained
    SQL Server 2008 : Advanced Stored Procedure Programming and Optimization - Using Dynamic SQL in Stored Procedures
    Mobile Application Security : BlackBerry Security - Development and Security Testing
    Inspecting Declarative Security Statements
    Windows Phone 7 Development : Using a WebBrowser Control to Display Dynamic Content
    Server-Side Browser Detection and Content Delivery : Mobile Detection (part 4) - Device Libraries
    Advanced ASP.NET : Understanding Caching
    Payload Smuggling
    Mobile Application Security : SymbianOS Security - Code Security
    SharePoint 2010 : Upgrading an Existing Extranet Solution from SharePoint 2007
    Linking PCs with a Network : Creating a Wired and Wireless Computer Network
    Security Fundamentals : Forms Authentication