How do I structure the UINavigation controller and

2019-09-15 02:01发布

问题:

I have a UINavigationController that needs to manage several view controllers. The navigation controller is in Take.m below, and each view controller in it's own file (see CamverViewController.m below). As a new XCode developer, I'm trying to figure out how to structure the application so events such as the tap of the button in the navigation bar can get access to the instance of the navigation controller to change the active view controller. I understand how to manipulate the view controllers, but need some advice on setting up the event handling.

Note: I have remove irrelevant methods from the sample source.

Any references, samples, advice, appreciated.

This class is there the UINavigationController and top level view controller are instantiated.

Take.m Source

@implementation Take

+ (UINavigationController*) createController {

//Controllers for navigation interface
CameraViewController *cameraViewController=[[CameraViewController alloc]init];

UINavigationController *navigationController=[[UINavigationController alloc]initWithRootViewController:cameraViewController];
navigationController.toolbarHidden=NO;

//Create tab bar item
navigationController.title=@"Take";
UITabBarItem *tabBarItem=[[UITabBarItem alloc]initWithTitle:@"Take" image:NULL tag:0];
navigationController.tabBarItem=tabBarItem;

[navigationController.view.window addSubview:navigationController.view];

return navigationController;
}

@end

This is the top level view controller which contains the navigation bar and right side button which, when clicked/tapped needs to change the view in the navigation controller. When this event is trapped the primary question is how to get access to the navigation controller in Take.m to manipulate the active view controller? CameraViewController.m

@implementation CameraViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
    // Custom initialization

    //Navigation bar items
    [self configureNavigationBarItems];

    //Toolbar for navigation interface
    [self configureToolbarItems];

}
return self;
}

-(void) configureNavigationBarItems{

//Add navigation bar items
//    [navigationController setNavigationBarHidden:YES];
UIBarButtonItem *categorizeButton=[[UIBarButtonItem alloc]initWithTitle:@"Categorize" style:UIBarButtonItemStylePlain target:self action:@selector(categorizeButtonHandler:)];
self.navigationItem.rightBarButtonItem=categorizeButton;

}

-(void) configureToolbarItems{

UISegmentedControl *options=[[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:@"Photo",@"Video", nil]];
options.segmentedControlStyle=UISegmentedControlStyleBar;
options.selectedSegmentIndex=0;
[options addTarget:self action:@selector(toggleSorting:) forControlEvents:UIControlEventValueChanged];

UIBarButtonItem *optionButton=[[UIBarButtonItem alloc]initWithCustomView:options];
UIBarButtonItem *spacer=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

self.toolbarItems=[NSArray arrayWithObjects:spacer,optionButton,spacer, nil];

}


#pragma mark - Event Handlers

- (void)categorizeButtonHandler:(id)sender
{
UIBarButtonItem *barButton=(UIBarButtonItem*)sender;

//How to access the navigation controller here???

}

@end

回答1:

It may seem a bit upside down, but UINavigationController is designed to be at the top of the view controller hierarchy. So you shouldn't be instantiating a navigation controller inside a UIViewController (which is what I'm assuming Take.m is)

The fact that you have a navbar appear at the top of your screen that you construct in your view controller may make it seem that your view controller contains a navigation controller - it doesn't. UINavigationController inserts it's navbar above your view controller for you (or you can turn it off and then UINavigationController just provides a great way to handle screen switching by calling push and pop).

Try adding a UINavigationController directly to window as rootViewController, then push your UIViewController onto the stack to display your first screen.

Then you access the UINavigationController using:

self.navigationController

from your view controller (the navigationController property will be set for you) and you can push a new VC, pop self, or set a new VC configuration using setViewControllers.