navigation controller is null when pushing new view - objective-c

I have a tab bar application and in one of those tabs I have a map view. I am trying to push a new view from clicking a disclosure button on an annotation on the map view using this code...
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
childController = [[AnnotationDetailView alloc] initWithNibName:#"AnnotationDetailView" bundle:nil];
[self.navigationController pushViewController:childController animated:YES];
}
however if I nslog the navigationController it is null.
What is confusing is that in another tab I have a table view which will push a view using the above code. Why does that work but an map annotation doesn't.

The simple answer is that your table view is inside a navigation controller and your map view isn't. A tab view controller isn't actually a navigation controller itself.
Depending on your project, the fix may be as simple as editing your XIB so that a navigation controller is the immediate child of the tab controller for the map's tab, and the map view controller is the child of that navigation controller. Look at how your table view is defined, and you should be able to see what's different.

Have you defined childController as AnnotationDetailView * childController; in your header?
or you can simply use:
AnnotationDetailView * childController = [[AnnotationDetailView alloc] initWithNibName:#"AnnotationDetailView" bundle:nil];

Related

Switch from view controller to custom tab bar controller

I have an application that has an initial view controller that allows the user to log in. After the users logs in I'm trying to change the view to a custom tab bar controller that is of class type TabViewController. The problem is that when I switch to the tab bar controller, the screen is black and the bottom tab bar is gray and empty.
Here is some relevant code:
in ViewController.m (initial log in view)
- (IBAction)logInButtonClicked:(UIButton *)sender
{
TabViewController *tabView = [[TabViewController alloc] initWithSession:session];
[self presentViewController:tabView animated:YES completion:nil];
}
in TabViewController.m (class assigned to the tab bar controller)
-(id) initWithSession: (Session*) s
{
self = [super init];
if (self)
{
session = s;
}
return self;
}
Note that when I do the default initialization like so:
TabViewController *tabView = [[TabViewController alloc] init];
I get the same result.
How can I make my tab view controller look like it does in my storyboard on initialization?
Storyboard:
What the tab view controller looks like in the simulator:
I'm not sure this is the best way but it's exact what I did in my last app and it works fine.
Try making the tab bar view controller the root/initial view controller of your app.
According to Apple's developer class reference:
When deploying a tab bar interface, you must install this view as the root of your window. Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller.
After doing this, set up a modal segue in the storyboard from the tab bar view controller to the login view controller, name it "segueLogin" and call it manually in viewDidAppear method of your tab bar view controller class.
if(!userHasLogin){
[self performSegueWithIdentifier:#"segueLogin" sender:self];
}
its really easy,
i will try to solve your problem in two step.
step 1-- select your TabViewController in storyboard and give it a identifier(below the custome class of TabViewController)
step 2--
- (IBAction)logInButtonClicked:(UIButton *)sender
{
UIStoryboard *storyBoard=[UIStoryboard storyboardWithName:#"Your_Story_Board_Name" bundle:nil];
TabViewController *tabView = [storyBoard instantiateViewControllerWithIdentifier:#"TabViewController_Identifier_From_Storyboard"];
[self presentViewController:tabView animated:YES completion:nil];
}
You should create your's TabViewController with UIStoryboard's - (id)instantiateViewControllerWithIdentifier:(NSString *)identifier
In yours case creating with [[TabViewController alloc] init] is wrong, you doesn't create all tabs programmatically.

How to hide the NavigationBar when i use SWRevealViewController embed in UINavigationController?

When i use SWRevealViewController as initial view or not embedded in UINavigationController the result is as i expected:
but when the SWRevealViewController comes from UINavigationController tee result is:
How can i avoid the NavigationBar presented in the Rear view?
Please add the following code to the viewWillAppear: method of the viewcontroller whose navigation bar you need to hide.
[super viewWillAppear:YES];
[self.navigationController.navigationBar setHidden:YES];
[self.navigationController.navigationBar.backItem setHidesBackButton:YES];
Try, this code for rear view controller
- (void)viewWillAppear:(BOOL)animated
{
self.navigationController.navigationBar.hidden = YES;
}
If you really need Navigation Controller on top of SWRevealViewController:
You got to hide navigation bar from navigation controller of your SWRevealViewController.
U can do this in IB (assuming you are using Storyboards):
Select Navigation Controller in your Storyboard
Open Attributes inspector
Find section "Navigation Controller", uncheck "Shows Navigation Bar"
Next, If you want navigation bard in front view controller, then attach it to separate Navigation Controller. You will have two Navigation Controllers, think on which one you want to push - it will have different effect.

How to access Tab View Controller from another View Controller

I'm having trouble accessing my view controllers under the tab bar controller. Here is what my storyboard looks like:
View Controller A (-> Page View Controller -> View Controller C
View Controller A -> Tab Bar Controller (MyTabBarController.h/.m) -> Navigation Controller (MyNavigationController.h/.m)-> View Controller B (TabViewController.h/.m)
Tab Bar Controller (MyTabBarController.h/.m) -> View Controller D
Tab Bar Controller (MyTabBarController.h/.m) -> View Controller E
From View Controller A I have an IBAction called loginButton that is connected to the Tab Bar Controller, and currently it looks like this:
- (IBAction)loginButton:(id)sender {
MyNavigationController *localNavigationController;
UIStoryboard * storyboard = self.storyboard;
MyTabBarController *tbc = [[MyTabBarController alloc] init];
NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:1];
TabViewController *login = [storyboard instantiateViewControllerWithIdentifier: # "TabViewController"];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:login];
localNavigationController.delegate = self;
[localControllersArray addObject:localNavigationController];
tbc.viewControllers = localControllersArray;
tbc.delegate = self;
tbc.moreNavigationController.delegate = self;
tbc.selectedIndex = 0;
[self presentViewController:tbc animated:YES completion:^{
}];
}
I'm not able to get this displayed correctly. I am getting a bunch of warnings in this piece of code. and it is also not showing the different tab items in the bottom of the Tab Bar, even though I have put images/text on each tab.
So how do I display/access the view controllers inside the Tab Bar Controller correctly? (ie View Controllers C/D/E)?
The storyboard that you show in your question already contains the tab bar controller, navigation controller, and login controller properly hooked up to each other. Because of that, you shouldn't be instantiating a new tab bar controller or navigation controller in code -- they will be instantiated by the storyboard when you instantiate the tab bar controller. So, the only thing you need to do, is to give the tab bar controller in the storyboard an identifier, and do this (assume the identifier is called MyTabBarController):
- (IBAction)loginButton:(id)sender {
UITabBarController *tbc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyTabBarController"];
[self presentViewController:tbc animated:YES completion:nil];
}
You wouldn't even need this code if you control drag from the "Login" button to the tab bar controller, and choose "Modal". That will create a modal segue which will present the tab bar controller with no code at all.
If you just want to select another tab from the tabBar controller then use something like this:
UITabBarController *tabBar = (UITabBarController *)self.window.rootViewController;
[tabBar setSelectedIndex:3];
Note that if the tabBar controller is the initial view controller you can grab an instance of it it the applicationDidFinishLaunching method and store it in the AppDelegate. Then you'll be able to access it like this:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
Remember to import the AppDelegate.h
I recommand you to use a Singleton shared instance to share multiple informations form multiple controllers.
It's a good design Pattern for you usage.
I'm writing samples of Design Patterns usage on cocoa (see https://github.com/leverdeterre/DesignPatterns -> Real singleton)

Modal UIViewController will not push to next UIViewController

The start of the structure is as follows...
UITabBarController -> UINavigationController(s)
From each of the UINavigationControllers, I have a UIBarButtonItem that modally presents a UIViewController.
This UIViewController has a MKMapView with pins at multiple locations. When clicked, they display an annotation with a disclosure button.
Within this UIViewController, it is my intention to push a detail page (UITableViewController) when pressing the disclosure button of the annotation. The method calloutAccessoryControlTapped: receives the appropriate pin, but the transition to the next controller fails.
I have tried every combination of the following methods...
[self.navigationController ...]
[self.parentViewController ...]
[self.parentViewController.navigationController ...]
with the method being either...
presentModalViewController:
pushViewController:
I have done all of these with the UIViewController being on its own, and also with it embedded inside of a UINavigationController.
All of these properties return null...
self.navigationController
self.parentViewController
self.parentViewController.navigationController
This is the first time I've used storyboard for an Xcode project. Am I missing a step?
Try getting rid of the code and implementing the transitions in storyboard by control dragging from the button to the view controller you wish to load modally. When the "Storyboard Segue" menu pops up select "modal". In the modal view controller, I like to use code to return from the modal by calling:
[self dismissModalViewControllerAnimated:YES];
To Presenting Storyboard View Controllers Programmatically scroll to that section in gravityjack on the link provided.
For example, I have a view controller that I created in storyboard which I can call programmatically with the following two statements:
SettingsViewController *settingsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"settingsVC"];
[self.navigationController pushViewController:settingsVC animated:YES];

UISplitViewController not calling delegate methods while pushing new detailView

I setup a storyboard based on the Master-Detail Application, embed the detail view in a navigation controller, and add a new table view controller object which I will use as a second detail view controller.
I then push the new detail view controller with the following code (instead of a segue because I am pushing both a root view and a detail view controller at the same time. Only the detail view code is shown).
// Push the detailView view controller:
NewClass *newViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"test"];
newViewController.navigationItem.hidesBackButton = YES;
self.splitViewController.delegate = newViewController;
[self.detailViewController pushViewController:newViewController animated:YES];
This works perfectly, EXCEPT that the splitView delegate methods are never called before or after the push. If I do this while in portrait mode, after it pushes the detailViewController, the button to drop down the masterView popover does not show up UNTIL I rotate to landscape mode and then back to portrait mode.
How can I cause the willHideViewController/willShowViewController split view controller delegate methods to be called or manually cause them to be called?
So from what I found, it doesn't call the method because the orientation hasn't changed.
What you have to do is to pass the button from the presenting view controller since it's already tied to the popover like this:
if(self.navigationItem.leftBarButtonItem != nil) {
newViewController.navigationItem.leftBarButtonItem = self.navigationItem.leftBarButtonItem;
}
// Push the newViewController