iOS custom navigation with nested view controllers
I am not exactly sure the best practice of doing this, so I thought I'd ask.
Here's the program's objective:
- A custom navigation controller created via a root UIViewController that does not actually subclass UINavigationController(To easily manipulate the design)
- Nested view controllers for different screens (manipulated by the main view controller)
- Ea开发者_StackOverflow中文版ch nested view controller has its own nib file
Currently, I have it working, however each nested view controller is not a view controller but a subclassed UIView. I feel like this is bad practice because I am using these UIViews in a view controller way but without the functions of a view controller (ie. viewDidLoad). Also, these UIViews are taking on the usual delegate methods of a UIViewController (which really sets off red flags).
Is this actually bad practice?
Things I am afraid of when trying to switch to UIViewControllers are that I would still have to make a subclass of UIView to identify which view to point to when I load the nib via:
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
for (id object in bundle) {
if ([object isKindOfClass:[SubclassedUIView class]])
currentScreenViewController = (SubclassedUIView *)object;
}
I haven't checked yet, but I assume I have to do "SubclassedUIView" rather than just UIView in that statement because there are other UIView objects in the bundle. But then again, that situation may be better off than the current one.
A different solution may be to make MainViewController a delegate for all of the UIViews that require a delegate and create categories of the MainViewController containing the delegate methods for each nested nib.
Any idea here?
Create a UIViewController
subclass for each SubclassedUIView
type, ticking the option to create a XIB file for the interface, and move all of the code over to that, pointing it to self.view
. Then open up Interface Builder with the .xib for that view controller and configure the visual appearance of the UIView
as much as you like. To manipulate visual elements from the main view controller you will have to either assign "Tag" numbers to each element or create a whole bunch of IBOutlet
instance variables and hook them up to your elements in IB. The way you present view controllers properly using a UINavigationController
is:
/* at the top of your main view controller */
#import "SubclassedUIViewController.h"
/* when navigating to the next view */
SubclassedUIViewController *newController = [[SubclassedUIViewController alloc] initWithNibName:@"SubclassedUIViewController" bundle:nil];
[(UILabel *)[newController.view viewWithTag:6] setText:@"Text"]; // example of accessing elements using tags
[newController.textLabel setText:@"Text 2"]; // example of accessing elements using IBOutlet connections
[self.navigationController pushViewController:newController animated:YES];
[newController release];
Interface Builder also allows you to add the navigation controller to your main view controller .xib file and provide the back button text, main title, etc. When you implement your subclassed view controllers, override initWithNibName:bundle:
and set self.navigationItem.title
and any other properties of self.navigationItem
you want.
EDIT: Did you mean you have to be able to manipulate specific properties of some of the subclassed views while in other ones? As in, you require access to all of them all the time? If this is the case then make connections to your subclassed views upon loading the main view controller, that is:
- (void)viewDidLoad
{
[super viewDidLoad];
self.subclassedController1 = [[SubclassedUIViewController1 alloc] initWithNibName:@"SubclassedUIViewController1" bundle:nil];
// self.subclassedController2 = ... etc
}
/* in your loading next view code you can skip the alloc/init line */
[self.navigationController presentViewController:subclassedController2 animated:YES];
And then in your subclassed controllers you can get to the main controller in a few ways:
- A call to
self.parentViewController
- A call to
[(MyCustomAppDelegateClass *)[[NSApplication sharedApplication] delegate] rootView]
or similar (basically, the reference your application delegate holds to the main view of the application). - By adding an
@property (assign)
property and ivar to the subclassed controller pointing to the main view controller. You can assign this on loading your main view controller withsubclassedController1.mainViewController = self
.
Helpful docs:
- View Controller Programming Guide for iOS: Navigation Controllers
- Xcode Quick Start Guide (updated for Xcode 4)
Apparently, what I was doing was sort of OK according to How to add an UIViewController's view as subview.
精彩评论