Push ViewController on AppDelegate from TabBar Application - objective-c

I have a Tab Bar application that shows several tabs. I case of notification I want user to be directed to a view controller with the ability to push "Back".
When my app was only Navigation controller app, I used this code in my AppDelegate:
UIStoryboard *mainStoryboard = self.window.rootViewController.storyboard;
DetailViewController *detailViewController = (DetailViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"detailViewController"];
[(UINavigationController*)self.window.rootViewController pushViewController:detailViewController animated:NO];
This code used to work fine until I converted my app to be Tab Bar. Seems like the "self.window.rootViewController" is not longer of type "UINavigationController" and therefore calling "pushViewController" generates an exception saying method doesn't exist.
Any way to make this work on a Tab Bar application?
Thanks

You should present your notification controller as modal (presentViewController:animated:completion:), and inside that controller you provide a way to close it, probably a button on top bar.
EDIT:
Thanks for Dimitry's answer I was able to go on the right track. I just had to make a small trick in order to preserve the top navigation bar and the bottom tool bar. I did it by using a "UINavigationController" instance. Here is the code:
UIStoryboard *mainStoryboard = self.window.rootViewController.storyboard;
DetailViewController *detailViewController = (DetailViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"detailViewController"];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
navigationController.navigationBar.tintColor = [UIColor blackColor];
navigationController.toolbar.tintColor = [UIColor blackColor];
[self.window.rootViewController presentViewController:navigationController animated:YES completion:NULL];

Related

modal segue to a xib from a xib?

I have an app that uses only xibs, no storyboards.
I have created a prompt xib that I would like to present modally (with the modal animation) from a table view controller xib (named TVC.xib) The TVC is nested in a navigation controller.
I can get the prompt to present itself, but I want it to present itself with a modal animation. Unfortunately, the presentModalViewController has been deprecated. What is the current option to present a view controller modally in code and have it animate the same way that modal presentations used to animate?
Here is my code: (in the TVC.m)
PromptViewController *promptVC = [[PromptViewController alloc] initWithNibName:#"PromptXib" bundle:nil];
UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:promptVC];
[self.navigationController presentViewController:navVC animated:YES completion:^{
NSLog(#"presented prompt vc");
}];
Ideally I could replace the method in the 3rd line with self.navigationController presentMODALViewController... etc, but it's deprecated.
You are looking for:
[self presentViewController:aViewController animated:animated completion:^{}];
But you should browse some tutorials to update the knowledge.
I've figured it out. I needed to set the transition style and presentation style on the view controller that I wanted to show. Here is my solution:
PromptViewController *promptVC = [[PromptViewController alloc] initWithNibName:#"PromptXib" bundle:nil];
promptVC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
promptVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:promptVC animated:YES completion:nil];

Build UITabBarController under UINavigationController

I have clean first page without UITabBarController , and UINavigationController is hidden , so when user went to second page , it will need UITabBarController with few tabs , so my question is how can i build a UITabBarController without make it rootViewController ..
in AppDelegate.m
MainViewController *mainviewController = [[MainViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:mainviewController];
[nav setNavigationBarHidden:YES];
self.window.rootViewController = nav;
in MainViewController.m after button get clicked
ShowViewController *showView = [ShowViewController new];
[self.navigationController pushViewController:showView animated:YES];
in ShowViewController.m
UIViewController *tm1 = [UIViewController new];
tm1.title = #"tm1";
tm1.view.backgroundColor = [UIColor redColor];
UIViewController *tm2 = [UIViewController new];
tm2.title = #"tm2";
UIViewController *tm3 = [UIViewController new];
tm3.title = #"tm3";
NSArray *tm = #[tm1,tm2,tm3];
UITabBarController *tabbarC = [UITabBarController new];
[tabbarC setViewControllers:tm animated:YES];
[[self navigationController] pushViewController:tabbarC animated:YES];
tabbarC didn't show .. xcode said : 2014-02-03 01:07:48.205 zhui002[45992:70b] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2014-02-03 01:07:48.355 zhui002[45992:70b] Unbalanced calls to begin/end appearance transitions for .
so could anyone tell me is that possible to use UITabBarController to build what i want , or i should build it with UIButton and make it looks like tabbar ?
thx !
The error Xcode is throwing most likely means you are trying to begin an animation before the previous animation has completed. You could try setting the animation property to NO in both the pushViewController calls to avoid getting the error.
A more elegant way to do what you are trying to do is make the ShowViewController a subclass of UITabBarController and set your tabs in viewDidLoad
The answer is yes you can. Hook up your TabBarController as a segue for 2nd ViewController. It will still be a part of the navigation controller.

How do I implement a UINavigationController in this case?

current version of my project :
I have 5 different UIViewControllers in my app. I've set my
FirstViewController to be the Initial View Controller using the
Attributes Inspector. I move back and forth from one ViewController to
another by using buttons to which I assign modal segues, from one
ViewController to another, using the StoryBoard
What I want to change:
I want to keep the navigation buttons obviously, delete the modal segues and use
a UINavigationController instead. If I understand the concept
correctly, when using a UINavigationController I need to go into each
UIButton-IBAction and at the very end of the method I have to push the next
ViewController I want to move to, onto my NavigationController (do I also
have to pop the current one first?). However, I can't figure out how
to implement all that correctly.
What I've done so far:
I removed all modal segues from the storyboard and kept the navigation buttons along with their corresponding IBActions
I unchecked the box in the Attributes Inspector that was making my FirstViewController the initial View Controller of my app
I went into my AppDelegate.m and tried to create the Navigation Controller there and make my FirstViewController be the RootViewController
MyAppDelegate.m
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIViewController *myFirstViewController = [[FirstViewController alloc] init];
UINavigationController *myNavigationController = [[UINavigationController alloc] initWithRootViewController:myFirstViewController];
[myNavigationController pushViewController:myFirstViewController animated:YES];
// Override point for customization after application launch.
return YES;
}
I then tried to test if the above was working by going into the IBAction of a
navigation button on my FirstViewController and implemented the
following in order to move to my SecondViewController when the
button is pressed :
FirstViewController.m
- (IBAction)goRightButton:(UIButton *)sender
{
// some code drawing the ButtonIsPressed UIImageView on the current View Controller
UIViewController *mySecondViewController = [[SecondViewController alloc] init];
[self.navigationController pushViewController:mySecondViewController animated:YES];
}
but nothing happens. What am I doing wrong ?
You are not linking your XIB file. Please add your navigation controller as
UIViewController *myFirstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
navigationController = [[UINavigationController alloc] initWithRootViewController:myFirstViewController];
Use following code to move from one view to another
UIViewController *mySecondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:mySecondViewController animated:YES];
If you are using a storyboard, you should just drag in the navigation controller there and hook it up to your app delegates. As long as it is the main storyboard, and you have identified a view controller to load first, you do not need to load any views in your app delegate.
In order to push a view programmatically that's in a storyboard, you need to do something like the following:
//bundle can be nil if in main bundle, which is default
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
MyCustomViewController *customVC = (MyCustomViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"customVC"];
//standard way
[self.navigationController pushViewController:customVC animated:YES];
//custom animation
[UIView transitionWithView:self.navigationController.view duration:0.5 options:UIViewAnimationOptionTransitionCurlUp animations:^{
[self.navigationController pushViewController:customVC animated:NO];
} completion:nil];
You identify the view controller with the identifier you add in the storyboard editor. Below are some screenshots to help show what I mean.

I have no Navigation Bar in a view called with an IBAction?

My main menu (a ViewController) is embedded in a NavigationController that I added in the storyboard in Xcode4.
I have a button in my menu, displaying a new view. To display it I use :
- (IBAction) display : (id) sender
{
if(!anotherView) anotherView = [[AnotherView alloc] initWithNibName:#"AnotherView" bundle:nil];
[self presentModalViewController:anotherView animated:NO];
}
My other view is correctly displayed with all its objects and elements. Excluding my NavigationController's bar, that doesn't appear. Why ?
Thanks for your advices
You are presenting the view modally what you probably meant was
[self.navigationController pushViewController:anotherView animated:YES]
of course what you really want to do is not mix and match storyboard and non storyboard flows unnecessarily like this and have the storyboard do this for you
you are presenting your viewController modally. If you want to use the navigation controller you have to push your view onto the navigation stack.
replace
[self presentModalViewController:anotherView animated:NO];
with
[self.navigationController pushViewController:anotherViewController animated:YES];
You can still present your view modally without losing the navigation bar. Try this code:
AnotherView *tempAnotherView = [[AnotherView alloc] initWithNibName:#"AnotherView" bundle:nil];
[self setAnotherView:tempAnotherView];
[tempAnotherView release];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:self.anotherView] autorelease];
[self.navigationController presentModalViewController:navController animated:YES];
Hope it helps! :)

Create a UINavigationBar without using [Projectname]AppDelegate?

I'm trying to create another UINavigationBar in my project, but it seems that I'm missing some key detail. When the application first loads, it does have it's own navigation system, but now I'm trying to add another navigation to a modal.
Many tutorials show you need to connect the view to the [self window], which only seems to work in the AppDelegate files, but when I've tried placing the code* in viewDidLoad, I can never seem to build without any errors.
I've seen this in multiple apps, but how is this done (programmatically or with IBuilder)?
Thanks!
Example code I've tried in viewDidLoad
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[self viewController]];
[self.window addSubview:navigationController.view];
You don't show enough code to be able to understand how you do it, but it seems to me that you are showing a controller modally, then trying to add as a subview to its view a navigation controller.
You can try and directly push modally your navigation controller (from your app delegate or where it makes sense for your app):
(IBAction) navigateToSecondaryViewController {
if (secondaryViewController == nil) {
informationTableViewController = [[SecondaryViewController alloc]
initWithNibName:#"SecondaryViewController"
bundle:[NSBundle mainBundle]];
secondaryViewController.delegate = self;
}
if (navController == nil) {
navController = [[UINavigationController alloc]
initWithRootViewController:secondaryViewController];
}
[self presentModalViewController:navController animated:YES];
}
Full example here.