I am a newbie in iOS application development, but I am trying to learn how to deal with Cocoa in the best way.
I got stuck trying to understand how to keep and refer
Abstract: I read carefully the topic Where to place the "Core Data Stack" in a Cocoa/Cocoa Touch application suggested by Brad Larson and I wrote a possible solution on how to deal with a model and different view controllers. The solution doesn't use Core Data, but I believe that the same design may be applied to Core Data apps.
Scenario: let's consider a simple application which stores information about products, such as name, description and price/unit. Once launched, the application shows a list of products (with a UITableView); when the user taps on a product name, the application presents product details in another view, updating the navigation bar with the product name.
Architecture The model is pretty simple here: an array of Product objects, each one with a name, a description and a price property.
The application has got three main views, mostly created by the Navigation template of Xcode: a UINavigationView (managed by the UINavigationController, instantiated in the app delegate), the default UITableView (managed by RootViewController and which is the first view shown by the UINavigationController) and a DetailView (managed by the DetailViewController class we have to write).
Let's see what's the big plan from the model point of view:
Here some code snippets:
Creation of the model:
// SimpleModelAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// products is a protected ivar
products = [[NSMutableArray alloc] init];
Product *p1 = [[Product alloc] initWithName:@"Gold" andDescription:@"Expensive metal" andUnitPrice:100];
Product *p2 = [[Product alloc] initWithName:@"Wood" andDescription:@"Inexpensive building material" andUnitPrice:10];
[products addObject:p1];
[products addObject:p2];
[p1 release];
[p2 release];
// Passing the model reference to the first shown controller
RootViewController *a = (RootViewController*)[self.navigationController.viewControllers objectAtIndex:0];
a.products = products;
// Add the navigation controller's view to the window and display
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
// The app delegate is the owner of the model so it has to release it.
[products release];
[_window release];
[_navigationController release];
[super dealloc];
}
The RootViewController can receive the model reference, since it has a NSMutableArray property:
// RootViewController.h
#import
@interface RootViewController : UITableViewController
@property (nonatomic, retain) NSMutableArray *products;
@end
When the user taps on a product name, the RootViewController instantiates a new DetailViewController and passes the reference to the single product to it using a property again.
// RootViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
// Passing the model reference...
detailViewController.product = [products objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
And, at the end, the DetailViewController shows the model information setting its outlets in the viewDidLoad method.
// DetailViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = product.name;
self.descriptionLabel.text = product.description;
self.priceLabel.text = [NSString stringWithFormat:@"%.2f eur", product.unitPrice];
}
You can download the full project here: http://dl.dropbox.com/u/1232650/linked/stackoverflow/SimpleModel.zip
I will really appreciate any comment to my solution, I am eager to learn ;)