removeFromParentViewController doesnot update UINavigationbar - objective-c

I want to remove all the viewcontrollers from UINavigationController. So I am using this code.
for (UIViewController* controller in navigationController.viewControllers) {
[controller removeFromParentViewController];
}
After that I create an new viewController and push it.
UIViewController* newVC=[[UIViewController alloc] init];
[navigationController pushViewController:newVC animated:YES];
Issue is all the viewcontrollers popout perfectly and adding newVC but on pushing newVC the navigationbar is getting a back button and title of newVC. On clicking back button it animates to the navigationbar of oldVC with title of oldVC that I have already removed in above loop;

removeFromParentViewController is a UIViewController method, so it's normal it has nothing to do with UINavigationBar
In the case of a UINavigationController the popViewControllerAnimated: method handles the removeFromParentViewControllerpart for you, along with navigation bar.
you can directly update the whole array of viewControllersof UINavigationController, calling `setViewControllers:animated:
see Replacing rootView in navigationController

[navigationController setViewControllers:[NSArray arrayWithObject:newVC]];

Related

dismiss rootViewController on button tap

I have a viewController instantiated by storyboard on application launch which is a part of hybrid app. On top of that I have presented one more view controller. Now While dismissing the presentedViewController I want to dismiss the rootViewController as well so as to show the hybrid app screen. How can I achieve this?
[self dismissViewControllerAnimated:YES completion:^{
// after your second view controller dismissed.
// set your new view controller as a root of window.
// You need to set navigation controller and set any root view controller for that navigation controller in storyboard.
// also don't forget to set identifier of your navigation controller.
UINavigationController* rootController = [[UIStoryboard storyboardWithName:kStoryboardName bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"controllerIdentifier"];
UIWindow* window = [[UIApplication sharedApplication] keyWindow];
window.rootViewController = rootController;
// this will set your new navigation controller with root view on UIWindow.
}];
OK, I don't know anything about Worklight. Or what a hybrid app is. So this may not make sense. But here's a strictly iOS answer to your question.
It doesn't really make sense to dismiss the root view controller without replacing it with another view controller. If you do, you would leave your app with no way to interact with it (except maybe shaking the phone?).
So there isn't a way to dismiss it as you can with child view controllers. But you can just remove it.
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
[keyWindow.rootViewController.view removeFromSuperview];
keyWindow.rootViewController = nil;
NSMutableArray *viewControllers = [self.navigationController.viewControllers mutableCopy];
[viewControllers removeObjectAtIndex:0];
[self.navigationController setViewControllers:viewControllers];

EXC_BAD_ACCESS at removeFromSuperview - using ARC

In one of my ViewControllers (ViewController A), I have the following code:
AlertViewController *aViewController = [[AlertViewController alloc] initWithNibName:#"AlertViewController" bundle:nil];
[self.view addSubview:[aViewController view]];
[self.view bringSubviewToFront:[aViewController view]];
And in AlertViewController, I have a button and when the user clicks on it, I have:
[self.view removeFromSuperview];
Whenever I click the button, the result is EXC_BAD_ACCESS.
I'm unable to figure out the problem. My project is using ARC and ViewController A is part of a navigation controller stack if that info helps.
The problem here is that the UIView doesn't own its UIViewController. In the first block of code you held the UIView around by adding it to a subview, but let the UIViewController go away. The UIView from a UIViewController is special, you can't let this happen.
Make sure the UIViewController that created the UIView lives as long as the view does.

How to presentModalViewController without dismiss the TabBarController

Hey guys i`m trying to present a modal view controller inside an application with a tab bar controller. The problem is, every time the new view is presented, it on top of my tab bar.
I need to keep my tab bar even when the view is presented. Like google maps application does with his toolbar at the bottom of the screen.
How can i do that?
Thank you
By default, a modal view controller is meant to take up the entire screen (on an iPhone/iPod, at least). Because of this, it covers whatever you have on screen at the time.
A view controller presented via modal segue is meant to live on its own. If you want to keep your Navigation and TabBar, then just use a push segue to present the new ViewController. Remember to use this kind of segue, your presenting controller needs to be part of a UINavigationController already.
Use this to push a ViewController. If it is a UINavigationController it will push its linked RootViewController by itsself.
Create a viewController to push: (Using Storyboard)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
or (Using Code/Nibs)
LoginViewController *viewController = [[LoginViewController alloc] init]; //initWithNibNamed in case you are using nibs.
//in case you want to start a new Navigation: UINavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
and push with:
[self.navigationController pushViewController:vc animated:true];
Also, if you are using Storyboards for the segues you can use this to do all the stuff. Remember to set the segue identifier.
[self performSegueWithIdentifier:#"pushLoginViewController" sender:self]; //Segue needs to exist and to be linked with the performing controller. Only use this if you need to trigger the segue with coder rather than an interface object.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"pushLiftDetail"]) {
[[segue.destinationViewController someMethod:]];
segue.destinationViewController.someProperty = x;
}
}
I think you'll need to add a UITabBar to the modal view and implement/duplicate the buttons and functionality that your main bar has. The essence of a modal window is it has total control until it is dismissed.
You might try putting your UITabBarController into a NavBarController, but I'm not certain that this will work.
UITabBarController -> NavBarController -> Modal View

UIViewController to know if it got pushed or popped?

I have a main UITableView, when cell is pressed it goes to another UITableView and when a cell is pressed there it goes to a DetailView of that cell.
I want the middle UITableView to behave differently depending on if the detailView got popped or the UITableView itself got pushed. If the view got pushed on from the main table I want to scroll to the top, if it is shown after a DetailView got popped I want it to stay at the same position.
Any suggestions?
you could call a scrollToTop method on the DetailViewController after you have pushed it to the navigationController.
Something like that:
if (!detailViewController) {
detailViewController = [[DetailViewController alloc] initWithNibName:nil bundle:nil];
}
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController scrollToTop];
// or use the tableView directly:
// [detailViewController.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
In your Middle View Controller, examine which view is next-to-display directly from the UINavigationController stack:
- (void)viewWillDisappear:(BOOL)animated
{
if ([self.navigationController.topViewController isEqual:(UITableViewController *)tvcDetailView]) {
// Detail view has been pushed onto the UINavigationController stack
}
else {
// Middle view has been popped from the UINavigationController stack
}
}
Create a BOOL #property on your middle UIViewController property called wasPushed or something similar, and when you initialise it from UIViewController 1, set the property on the new instance, push it onto the nav stack and you can then use your property in your middle view controller's loadView, viewDidLoad, viewWill/DidAppear methods.
As soon as you've used it, set it back to FALSE or NO (or whatever) and when you end up coming back to it due to popping off your 3rd view controller you'll have it as FALSE/NO in your loadView, viewDidLoad etc.. methods.

Objective C: How to present modal view controller from appdelegate?

I am in the appdelegate of my application. How can I add a modal view controller in the "didfinishlaunching" method?
I tried the following but did not work
SomeViewController *vc = [[SomeViewController alloc]init];
[self.tabController.navigationController presentModalViewController:vc animated:NO];
EDIT:
I changed my implementation to the following
self.tabController.selectedViewController
= [self.tabController.viewControllers objectAtIndex:0];
SomeViewController *vc = [[SomeViewController alloc]init];
[self.tabController.selectedViewController presentModalViewController:vc animated:NO];
I checked that the 'selected view controller' is not null... however I am still not able to get the output I needed. Is there anything I am missing?
Assuming tabController and navigationController are not nil, the applicationDidFinishLaunching may be too soon to display the modal view controller.
Make sure you put that code after you make the window key and visible. [self.window makeKeyAndVisible];
If that does not work try listening for the UIWindowDidBecomeKeyNotification for that window
You can try delaying presentation of that modal a few seconds using performSelector:withObject:afterDelay: