Manage Multiple ViewControllers from a TableView
I'm curious if anyone has ideas for managing multiple ViewControllers from a TableView. I have a list of roughly seven items I am displaying in a TableView with a ViewController dedicated to each. My first thought is to initialize an array with the various ViewControllers.
NSMutableArray *viewControllers = [[NSMutableArray alloc] initWithCapacity:7];
[viewControllers addObject:[[ViewController1 alloc] initWithNibName:@"View1" bundle:nil]];
[viewControllers addObject:[[ViewController2 alloc] initWithNibName:@"View2" bundle:nil]];
...
Then reference that array to load the appropriate view on item selection.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.navigationController pushViewController:[viewControllers objectAtIndex:indexPath.row] animated:YES];
}
I'm really not sure if this is an appropriate approach. Any direction would be great.
EDITED:
Based on the feedback from Ryan and Joe I implemented an object to hold my table items. Abbreviating my problem also caused some confusion on implementation details. Added the full solution to manage both view controllers and selecting tab bar items.
TableNavigationItem.h
#import
@interface TableNavigationItem : NSObject {
NSString *title;
NSNumber *tabIndex;
id viewController;
}
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSNumber *tabIndex;
@property (nonatomic, retain) id viewController;
@end
TableNavigationItem.m
#import "TableNavigationItem.h"
@implementation TableNavigationItem
@synthesize title;
@synthesize viewController;
- (id) init{
if(self = [super init]){
self.title = @"";
}
return self;
}
- (void) dealloc {
[title release];
[tabIndex release];
[viewController release];
[super dealloc];
}
@end
Then initialize per Joe's suggestion.
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithCapacity:7];
TableNavigationItem *navItem;
// view 1
navItem = [[TableNavigationItem alloc] init];
navItem.title = @"View 1";
navItem.tabIndex = [NSNumber numberWithInt:1];
[mutableArray addObject:navItem];
[navItem release];
// view 2
navItem = [[TableNavigationItem alloc] init];
navItem.title = @"View 2";
navItem.viewController = [ViewController2 class]];
[mutableArray addObject:navItem];
[navItem release];
...
// store the navigation items
self.tableItems = [NSArray arrayWithArray:mutableArray];
[mutableArray release];
Then
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
TableNavigationItem *navItem = [tableItems objectAtIndex:indexPath.row];
if(navItem.viewController != nil){
[self.navigationController pushViewController:[[[navItem.viewController alloc] init] autorelease] animated:YES];
}
else if(navItem.tabIndex != nil){
[((MyAppDelegate *)[UIApplication sharedApplication].delegate).tabBarController setSelectedIndex:[navItem.tabI开发者_如何学Cndex integerValue]];
}
}
If all the views those controllers manage are visible on the screen immediately, there is nothing wrong with that approach. Make sure you release the array of VC's in -viewDidUnload
, and recreate it in -viewDidLoad
, so the runtime can unload all those extra objects when the next view is pushed onscreen. And be aware, only the root view controller will receive view lifecycle events; The view controllers you create and manually add the owned views to the table will not get those methods called. You'll have to implement some plumbing to get those view lifecycle events into the 'subviews', through notification or delegation.
The best answer to your question is "Instrument it". Run the Allocations and VM instruments at a minimum, and check to see how much memory those view controllers are consuming. If you want to improve your skillz with Instruments, watch the Performance session from WWDC 2011, they did a great job teaching how to use it to find memory and performance issues.
That sounds fine to me. The only concern I would have is whether your view controllers are RAM-heavy, in which case you may want to make a decision: is it better to preallocate everything (i.e. are you sure you can fit all of those controllers' state within available memory?) or is it better to take the latency hit to load the appropriate view controller as-needed?
It looks like your ViewControllers are of different classes. If that's the case (and if each one always uses the same respective nib), I would consider implementing a custom -init
method on each and making your array of choices one of Class
objects. That's just a matter of personal preference, though.
One more thing: You will want to autorelease those view controllers or you'll leak memory no matter what.
精彩评论