I am having problems presenting a view controller from an action sheet in iOS 7. My program just seems to skip over:
[self.navigationController presentViewController:viewController animated:TRUE];
Has anyone else encountered this problem?
Thanks.
self.navigationController is nil if the view controller is not embedded inside a navigation controller. Sending a message to nil is ignored (which is why your program is skipping over that line).
Change self.navigationController to self, or self.tabBarController if you're using a tab bar controller, or self.splitViewController if you're using a split view controller.
try with
[self presentViewController:viewController animated:YES completion:nil];
Try present new view controller in - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
Related
EDIT: Added code that contains the dismissal.
NEW DATA
The problem remains the same as the problem listed under old data, except the dismissal line has changed.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Yes"])
{
NSLog(#"Calling Dismissal...");
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
}
The function is being called because "Calling Dismissal..." is displayed in the log.
Current Hierarchy: UITabBarController - NavigationController/NavigationController - View1/View2
OLD DATA
In case the question was confusing, I am trying to dismiss a UITabBarController than I presented modally. The UITabBarController does use NavigationControllers to setup the two views inside. However, no matter how many parentViewController s I put in
(i.e.):
[self.parentViewController.parentViewController.etc... dismissViewControllerAnimated:YES completion:nil];
The UITableBarController will not dismiss. I have a button being placed in the NavigationController of both views that is calling the line of code above. Any hints on how to dismiss the UITableViewController?
The presenting view controller, which is not the same concept as the parent view controller, needs to dismiss it. This code:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
will typically do the trick.
However, depending on what this controller's function is, I usually prefer to have my presented controllers send a delegate message or NSNotification to the parent, so the parent can extract whatever data it needs before dismissal.
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];
I'm building an app that currently has 3 ViewControllers. One of them is used after a successful login so is not relevant in this question.
I'm using a mixture of Storyboards and building things programmatically when I find Storyboards do not give me the fine control that I need.
The first ViewController is built in my 'MainStoryboard'. It has a login form and an info button at the bottom. I link it up the my AppDelegate by doing the following inside didFinishLaunchingWithOptions:
ViewController *viewController = (ViewController *)self.window.rootViewController;
Because I wanted to force rendering of a UIWebView (another story) I create the second view programmatically. I do the following inside didFinishLaunchingWithOptions:
infoViewController = [[InfoViewController alloc] init];
[infoViewController view];
Inside both of my ViewControllers I setup a link to appDelegate as below:
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
I have an info button in my first ViewController that takes you to the infoViewController. It calls the following code when tapped:
appDelegate.infoViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:appDelegate.infoViewController animated:YES];
The above works just fine for me, flips over the screen and shows the InfoViewController.
On my InfoViewController I have a button that should take you back to the login page, I have tried all sorts to get this to work but it just crashes my app. Nothing seems to work. I have tried the following:
appDelegate.viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:appDelegate.viewController animated:YES];
and
[self.navigationController popToRootViewControllerAnimated:YES];
and
[self.navigationController popViewControllerAnimated:YES];
and
[self.navigationController popToViewController:appDelegate.viewController animated:YES];
I suspect the last 3 might be more to do with when you have a navigation view controller and you want to go back to the root? I'm not sure, but either way it does not work. I had this working using storyboards previously so I'm sure it ought to be easy! As mentioned I switched to making the infoViewController programmatically so that I could force the UIWebView to render before the view appeared.
Any help much appreciated.
You can do with:
[self dismissModalViewControllerAnimated:YES];
You should use this.
[self dismissModalViewControllerAnimated:YES];
You should use a main controller for switching between your other view controllers. Change the view of your root controller to one of your other view controllers (apply animations as usual if needed). Hold a pointer to your root controller in your other view controllers and call self.rootController.view = <desired_controller_instance>.view
I think the way you're presenting your InfoViewController is wrong. Do it the following way:
In your ViewController, create an action for the info button.:
- (IBAction)infoButtonTapped:(id)sender
{
InfoViewController *infoViewController = [[InfoViewController alloc] init];
infoViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:infoViewController animated:YES];
}
And in your InfoViewController, in the action of your button that should take you back write this:
- (void)takeBackToViewController
{
[self dismissModalViewControllerAnimated:YES];
}
Hope it works.
Also in presented controller you can use this
if(self.parentViewController)
[self.parentViewController dismissModalViewControllerAnimated:YES];
else
[self.presentingViewController dismissModalViewControllerAnimated:YES];
To dissmiss current controller.
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];
Using a Modal View from a TabBar View
I always get the following error:
Error from Debugger: Previous Frame identical to this frame (gdb could not unwind past this frame)
I have an App using a TabBar. From one of the TabViews I need to display
a View modally. I try:
if(self.gmailController == nil) {
self.gmailController =
[[GMailViewController alloc] initWithNibName:#"GMailView" bundle:nil];
}
[[self.navigationController]
presentModalViewController:gmailController animated:YES];
////////
And I have tried:
[self.parentViewController
presentModalViewController:gmailController animated:YES];
and
[self.tabBarController presentModalViewController:gmailController animated:YES];
and
[self presentModalViewController:gmailController animated:YES];
Thanks for reading! Any comments welcome.
Mark
Check all the connections in your NIB files. I was getting this same error after I changed the name of an IBOutlet variable but forgot to adjust the NIB. This broke the connection between the ViewController and the NIB.
I am sorry. This problem involved my error. I had a problem with the nib file
loading. Once I fixed the NIB, the Modal View loaded with:
[self.tabBarController presentModalViewController:gmailController animated:YES];