How to switch to another view - cocoa-touch

The following code should work, right?
ViewController2 *childView = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
[self.navigationController pushViewController:childView animated:YES];
[childView release];
It doesn't do anything though. There are no error messages. The view just doesn't get switched. viewDidLoad does not even execute inside ViewController2.

That code won't do anything if the view controller presenting it doesn't have a navigation controller, i.e. it isn't in a navigation controller stack. In that case, you'll be calling a method (pushViewController:animated:) on a nil object (self.navigationController) which does nothing. Thus, you can only use this this method if the "parent" view controller is in a UINavigationController stack.

Use this:
[self presentModalViewController:viewControllerNameHere animated:YES];

Related

Wrong 'presentingViewController'

In my MainViewController, I present another view controller through this:
MessageViewController *messageController = [[MessageViewController alloc]initWithNibName:nil bundle:nil];
[messageController setModalPresentationStyle:UIModalPresentationFullScreen];
[messageController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:messageController animated:YES completion:nil];
[messageController release];
This will display the view controller correctly. However, when I try to go back to the presenting view controller, which in this case should be the MainViewController, this code doesn't work:
if ([self.presentingViewController isKindOfClass:[MainViewController class]])
[(MainViewController *)self.presentingViewController setCurrentViewTag:2];
[self dismissModalViewControllerAnimated:YES];
I removed the "if.." condition to force it in setting the current view tag. An error occurred telling me that the presenting view controller seems to be the UINavigationController:
[UINavigationController setCurrentViewTag:]: unrecognized selector sent to instance 0x8352a50
Can anyone tell me why is this happening? This code used to work before and I am not sure what changed to make it stop working properly.
EDIT
Here is the updated code:
ReaderController *readerController = [[ReaderController alloc]initWithNibName:nil bundle:nil];
[readerController loadWhichViewToShow:2];
[self setDefinesPresentationContext:YES];
[readerController setModalPresentationStyle:UIModalPresentationFullScreen];
[readerController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:readerController animated:YES completion:nil];
[readerController release];
Calling [self presentViewController:messageController animated:YES completion:nil]; doesn't necessarily use the vc you call this on to present the other vc. By default it travels up the vc-hierarchy and presents the other vc on the root view controller. That's why in your case the presenting view controller is a UINavigationController.
If you want to force your MainViewController to be the presenting vc, you have call:
[self setDefinesPresentationContext:YES];
on your MainViewController before presenting the MessageViewController.
Edit: In case someone else reads this: definesPresentationContext seems to be bugged or the documentation is wrong. See the comments below and Cocoa Builder
copy of my answer from this question
from Programming iOS 6, by Matt Neuburg:
On the iPad, when the presented view controller’s modalPresentationStyle is UIModalPresentationCurrentContext, a decision has to be made as to what view controller should be the presented view controller’s presentingViewController. This will determine what view will be replaced by the presented view controller’s view. This decision involves another UIViewController property, definesPresentationContext (a BOOL). Starting with the view controller to which presentViewController:animated:completion: was sent, we walk up the chain of parent view controllers, looking for one whose definesPresentationContext property is YES. If we find one, that’s the one; it will be the presentingViewController, and its view will be replaced by the presented view controller’s view. If we don’t find one, things work as if the presented view controller’s modalPresentationStyle had been UIModalPresentationFullScreen.
TL;DR
1. set definesPresentationContext to true on the desired presentingViewController
2. set modalPresentationStyle to UIModalPresentationCurrentContext on the desired presentedViewController
If seems that you need to set three thing in iOS 11.
controller.modalPresentationStyle = UIModalPresentationCurrentContext;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
self.definesPresentationContext = YES;
[self presentViewController:controller animated:YES completion:nil];

When do views get created?

I apologize in advance for the n00b question. I am just getting started w/ iOS!
I am trying to push a webViewController onto a navigation controller.
mudWebViewController *webViewController = [[mudWebViewController alloc] initWithNibName:nil bundle:nil];
[[webViewController webView] setDelegate:webViewController];
[[self navigationController] pushViewController:webViewController animated:YES];
But this doesn't seem to work, as I don't see any of the logs in the delegate messages.
If I set the delegate in the viewDidLoad: method, it works fine.
I guess the webView doesn't actually exist at that point, but why? If I initialize the controller, shouldn't the webView be initialized too?
Is viewDidLoad: the right place to be setting up this stuff?
initWithNibName should be not nil, since you obviously are using a nib file to build the view, else you have to create the view in code, which you don't
mudWebViewController *webViewController = [[mudWebViewController alloc] initWithNibName:#"webViewController" bundle:nil];
[[self navigationController] pushViewController:webViewController animated:YES];
Also any delegates should be set either from the Interface builder or from the view itself in the viewDidLoad delegate and not from the previous class, as the object might not been yet initialized in the code so it can fail to set the delegate properly.

view controller pushed from navigation controller is not displayed

I have a navigation view controller that pushes "viewController1" properly. Then, from "viewController1", goToApp function is called in order to push "appViewController". Function goToApp is executed but aplication remains at same view, "viewControlller1". How to push it? Thank you.
from viewController1:
navigationViewController *theInstance = [[navigationViewController alloc] init];
[theInstance goToApp];
in navigationViewController:
-(void)goToApp {
appViewController *AppsViewController = [[appViewController alloc] initWithNibName:#"appViewController" bundle:nil];
[[self navController] pushViewController:AppsViewController animated:YES];
[AppsViewController release];
}
goToApp executed but appViewController not launched.
You should not create a new UINavigationController in viewController1. You should get it through the property navigationController. That property will return the UINavigationController that has the UIViewController on it's stack (if any, so it can be nil).
UINavigationController * theInstance = self.navigationController;
[theInstance goToApp];
See: http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html property navigationController.
Besides that, it is a better convention to name your pointers correctly to what they represent. I would suggest to rename theInstance to currentNavigationController or just navigationController.

How to remove multiple many view from superview

I have some uiview, one call another in this way:
From first uiview:
MyViewController *contr1 = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[self.view addSubview:contr1.view];
From second uiview:
MyViewController2 *contr2 = [[MyViewController2 alloc] initWithNibName:#"MyViewController2" bundle:nil];
[self.view addSubview:contr2.view];
now in the third uiview i want to return back on the first updating it ( calling viewDidLoad ). how can i do?
First of all - you are doing it wrong.
Since you are using view controllers present them modally or push them:
MyViewController2 *contr2 = [[MyViewController2 alloc] initWithNibName:#"MyViewController2" bundle:nil];
[self presentModalViewController:contr2];
If you want to dismiss modal controllers exactly to your root view controller you should obtain a pointer to it in the controller you are currently using and send it a message to dismiss every modal view that there is on it.
- (IBAction)doHomePage:(id)sender {
MyAppDelegate *appDelegate = (MyAppDelegate *)[UIApplication sharedApplication].delegate;
[appDelegate.navigationController.rootViewController dismissModalViewControllerAnimated:YES];
}
Also instead of viewDidLoad: you might want to use viewWillAppear: or viewDidAppear:.
Sorry beforehand if there are some typo errors in the code since I wrote it by hand.

"EXC_BAD_ACCESS" in switching to another view

I have MainMenuViewController with button which action is
- (IBAction) goToFirstView {
FirstViewController *fvc = [[FirstViewController alloc] init];
[self.view addSubview:fvc.view];
[fvc release];
}
FirstViewController have UIButton with action
- (IBAction) rightArrow {
SecondViewController *svc = [[SecondViewController alloc] init];
[self.view addSubview:svc.view];
[svc release];
}
But when I press "rightArrow" button app crashes with "EXC_BAD_ACCESS". Can't found my problem. Help me please.
[svc release];
The problem is here. When releasing the view controller, the view's events will target a freed object, and make your program crash (probably in viewDidLoad or viewDidAppear if it's instant but it doesn't matter). Note that a view does not (normally, AFAIK) retain it's view controller, if that might have been your assumption...
When you say [self.view addSubview:svc.view] you're adding SecondViewController's view to FirstViewController's view. Similar with MainViewController and FirstViewController. What you'll end up with is a view hierarchy that looks like this:
main view
first view
second view
I doubt that's really what you want. Instead, use a navigation controller with your MainViewController as the nav controller's root controller, and then use -pushViewController:animated: to push the controllers (not the views!) onto the navigation stack.