The article your reference is a good one - like you I like to inject a model into the controller (an old habit from Smalltalk days - in particular Dolphin Smalltalk follows this pattern quite extensively).
I have found that most of my controllers have init methods like the following:
- (id)initWithItem:(id<Nameable>)item addingTo: (id<ModelContainer>)model {
if (self = [self initWithNibName:@"ItemEditTableToolbarView" bundle:nil]) {
self.namedItem = item;
self.container = model;
}
return self;
}
You can then call your controller like this:
ReDoListEditController *itemViewController = [[ReDoListEditController alloc] initWithItem: item addingTo: model];
[self.navigationController pushViewController: itemViewController animated: YES];
[itemViewController release];
Notice that I embed the name of my Nib file in the init method (you could make that another parameter if you need more flexibility - but I haven't yet found any of my controllers need to be generic. This is interesting - as in Dolphin, controllers (and their views) can be very compositional - so often in your init method, you would be picking out sub models from your model and calling init for your sub components. I think this might be possible on the iPhone with IB but I haven't explored this idea yet.
However you need to do a bit of additional work to pass your model to the very first controller (this was something I hadn't initially figured out).
- Create a Window Based application in XCode (if you want navigation based app, you can add this with code fairly easily)
Edit "YourAppDelegate.m" and change the applicationDidFinishLaunching: method to something like the following:
viewController = [[AppRootViewController alloc] initWithModel: [application model]];
viewController.view.frame = [[UIScreen mainScreen] applicationFrame];
[window addSubview: viewController.view];
[window makeKeyAndVisible];
If you want to use another project type, the following instructions also seem to work but its a lot more effort (I simplified to the above):
- Delete your MainWindow.xib file (sounds radical, but you want to create the MainWindow yourself - you can still create all your other views with IB)
- Edit your .plist file and remove the MainWindow.xib entry (its usually the last item)
Edit your main.m file and change the UIApplicationMain line (replacing the last parameter with the name of your existing app delegate) - e.g.:
int retVal = UIApplicationMain(argc, argv, nil, @"YourAppDelegate");
Edit "YourAppDelegate.m" and change the applicationDidFinishLaunching: method to something like the following:
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
viewController = [[AppRootViewController alloc] initWithModel: [application model]];
viewController.view.frame = [[UIScreen mainScreen] applicationFrame];
[window addSubview: viewController.view];
[window makeKeyAndVisible];
I have added a category method to UIApplication called:
- (MyModel *)model;
You can then get your model from the application (like I show above) and also in other places in your application e.g.
viewModel = [[UIApplication sharedApplication] model];
Although if you always pass it into your view controller like I have described, this is probably a code smell.