dismissViewControllerAnimated shows a white screen - objective-c

I got a ViewController named viewControllerA which presents ViewControllerB with this common code:
ViewControllerB *viewControllerB = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"Identifier"];
[self presentViewController:viewControllerB animated:YES completion:nil];
viewControllerB is a UITabbarController but when calling
[self dismissViewControllerAnimated:YES completion:nil];
from one of the TabbarControllers ViewControllers (say page 2) I just get a white screen. I was expecting to see viewControllerA but instead I just see an empty screen.
also
NSLog(#"%#", [[self presentingViewController] class]);
logs viewControllerA.
Does anybody know why I get a empty white screen instead of viewControllerA?
EDIT
I put a breakpoint on viewDidAppear in viewControllerA and it does break there when calling dismissViewControllerAnimated. But how is it possible that it only shows a white screen?
Also I think you should know that viewControllerA's layout is created programatically. viewControllerB is created much later and in the meantime we decided to use a storyboard so viewControllerB's layout is created with storyboard.

you can remove your self (in viewcontrollerB)
[self.presentingViewController dismissViewControllerAnimated:NO completion:nil];

If you present viewControllerB from viewControllerA using
[self presentViewController:viewControllerB animated:YES completion:nil];
you should probably call [self dismissViewControllerAnimated:YES completion:nil]; in the viewControllerA, but not from one of the of the pages of your TabBarViewController.

Related

Switching storyboard view controller in Objective-C

I am trying to switch to different ViewController on same storyboard like so:
CalendarViewController *CalViewController = [[CalendarViewController alloc] init];
[self presentViewController:CalViewController animated:NO completion:nil];
When I run this action, corresponding implementation file executes NSLog message but screen goes black with no errors being displayed.
How do I fix this?
Let's suppose you created your CalendarViewController interface in a storyboard, and you assigned it the identifier "ControllerIdentifier".
If you want to load it from inside another View Controller, you can instantiate your CalendarViewController and present it like this:
CalendarViewController *calViewController = (CalendarViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"ControllerIdentifier"]
[self presentViewController:calViewController animated:NO completion:nil];
You can use Segue to push calViewController.
You can use the code below;
CalendarViewController *CalViewController = (CalendarViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"CalendarViewControllerIdentifier"];
[self presentViewController:CalViewController animated:NO completion:nil];
But if you choose the second option, you have to set CalendarViewController's Storyboard Identifier to CalendarViewControllerIdentifier from your storyboard.

close modalvew controller and parentview

I am trying to open a modalview from a view like that,
SignupViewController *signUpView = [[SignupViewController alloc] initWithNibName:#"SignupViewController" bundle:nil];
[signUpView setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
self.parentViewController.view.transform = CGAffineTransformMakeScale(1.3, 1.3);
self.parentViewController.view.alpha = 0;
[UIView animateWithDuration:.35 animations:^{self.parentViewController.view.alpha = 1.0; self.parentViewController.view.transform = CGAffineTransformMakeScale(1, 1);}];
[self presentModalViewController:signUpView animated:YES];
After login i am closing the modalview and redirecting to anther view, but the parentview is still there,
[self dismissViewControllerAnimated:YES completion:^{
ToolsViewController *gototoolpage = [[ToolsViewController alloc] initWithNibName:#"ToolsViewController" bundle:nil];
[self.navigationController pushViewController:gototoolpage animated:YES];
}
How to dismiss the parentview also. Any idea
You code looks a little confused. What do you intend by references to parentViewController? Check the docs - it is the containing viewController, not the previous or presenting viewController. In a NavigationController context this would be the UINavigationController. In a modal view context there is no parentViewController, but there is a presenting ViewController. I am not sure what you intend by all of those calls to self.parentViewController.
In any case you should really be sending the dismiss request back to your presenting viewController via a delegate so that it is completely clear where the pushViewController message is being passed from and to.
In the header file of your signUpViewController declare a protocol:
#protocol SignUpViewControllerDelegate
- (void) dissmissSignUpVC;
#end
then in your presentingViewController, after
SignupViewController *signUpView = [[SignupViewController alloc] initWithNibName:#"SignupViewController" bundle:nil];
add
[signUpView setDelegate:self];
and implement the delegate method with the same code you now have in your completion block:
- (void) dissmissSignUpVC {
ToolsViewController *gototoolpage = [[ToolsViewController alloc]
initWithNibName:#"ToolsViewController" bundle:nil];
[self.navigationController pushViewController:gototoolpage animated:YES];
}
In signUpView invoke the delegate's method to dismiss:
[[self delegate] dissmissSignUpVC];
Watch out for those stacked animations, I suspect that only the first will be performed (i.e. gototollpage animated:YES might as well be gototoolpage animated:NO)
Perhaps anyway you should reconsider your logic. I imagine the user might have a confusing experience if you do this under-the-hood manipulation of viewControllers. Better that there is a UI control for the user to navigate to toolsViewController so they understand where they are?

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];

How to present the same modalView after dismissing it once

I'm having some problem trying to present a modal view controller after it has been presented the first time, so I just start a little test method, it presents, dismisses and presents again the same controller modally.
// This is just test Code.
MYViewController *vc = [[MYViewController alloc] init];
[self presentModalViewController:vc animated:YES];
[self dismissModalViewControllerAnimated:YES];
[self presentModalViewController:vc animated:YES];
I get the error:
2011-11-15 09:50:42.678 Proyecto3[1260:11603] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller <RootViewController: 0x6d9d090>.'
The documentation does not add any clue here.
#David, make the MYViewController an instance variable, and initialize it like this:
if (myInstance==nil)
//create instance of MYViewController
//myInstance.delegate=self
//present modal VC
In MYViewController create a protocol to co-ordinate dismissing MYViewController may be on a done or cancel button. In the button action call some thing like
done
{
if([delegate respondsToSelector:#selector(willDismissModalView)])
{
[delegate willDismissModalView];
}
}
and in willDismissModalView method of your VC dismiss MYViewController. This way you can do it 'n' times.
In your code [self dismissModalViewControllerAnimated:YES];
will do nothing to the modalViewController,since here the "self" is the viewController from where you are trying to present a modalViewController "vc".Again you are presenting a modalViewController which is already presented.this will result in a termination.
You can dismiss the modalViewController vc in that viewController,here vc.
You cannot present/dismiss the view controller while it is animated, I think this works
MYViewController *vc = [[MYViewController alloc] init];
[self presentModalViewController:vc animated:NO];
[self dismissModalViewControllerAnimated:NO];
[self presentModalViewController:vc animated:YES];
But I don't really see any reason for doing it, why would you want to dismiss and re-present a modal view controller which is already presented?

Identify when I return to ViewController

I have two views with their controllers.
The application start with the FirstViewController.
Then with a button I open the SecondViewController.
With other button I dismiss the SecondViewController to return to FirstViewController.
Is there any way to detect that in FirstViewController that it has recovered focus?
EDIT: Ok I look the answers and I use viewWillAppear but don't work if I use a UIModalPresentationFormSheet.
-(IBAction)openSecondView{
SecondViewController *screen = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
screen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
screen.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:screen animated:YES];
[screen release];
}
And close this view with close button.
viewWillAppear never called.
implement UIViewController's viewWillAppear method
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
}
Add a delegate (Protocol) method. Call the delegate method just before dismissing the SecondViewController.
For more info on delegate, see delegate
implementation of the viewWillAppear: callback will work only if you use navigation controller or tabbarcontroller for displaying another controller + with such approach you will need to check somehow if this is only the first appearance of the view, or was called by any other reason;
using a delegate, as described by Gomathi above is a much better option!
Depends how you are setting up the first view controller. Encapsulate it within UINavigationViewController (and if you do not want the navigation bar, you can always set it to hidden ( [self.navigationController.navigationBar setHidden:YES] ). ViewWillAppear will work then.
inside the viewWillAppear of the FirstViewController
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(#"view 1 focused");
}