I'm presenting UIViewController B modally from UIViewController A. Then, there is a UINavigationController between B and C, and C is flipped from B. I want to dismiss both B and C and animate straight to A, without showing B and hence without calling B's viewDidLoad function. I'm calling dismissViewControllerAnimated from A, but that still shows B first and hence calls B's viewDidLoad function. Forgive me if there is already a SO answer on this; I've been snooping around for hours and just can't find an answer. How can I solve this?
Any Parent ViewController that is presented modally can be dismissed using:
[self.parentViewController dismissModalViewControllerAnimated:YES];
Another way to do it would be using:
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Let me know if it doesn't works.
Related
So I have view controller A, B, and C.
From A, I present VC B modally over the current context.
There is a button in VC B from where I present VC C (using segue)
Now on dismissing Viewcontroller C, I am trying to dismiss VC B and from VC A, run some function which again presents VC B based on some logic.
But in this case, I get this error "Attempt to present UIViewController on UIViewController whose view is not in the window hierarchy"
I have tried to dismiss with a completion handler, dispatchQueue(after:)
but those doesn't work.
On the contrary, I have a UIButton attached in VC A, which runs the same logic for presenting VC B and it is running correctly and not showing any error.
What am I missing in this scenario?
I hope these two solutions help you.
I had the same problem these two solutions helped me with this issue.
First:
Post notification in VC C viewDidDisappear or in your button click method and add its receiver on VC B which you want to close it after closing VC C.
Second:
You can create a protocol While clicking the button call your protocol method and pass your data to your viewController.
How can I go back to a viewController that was already segued from another VC without Nav Controller embed?
Meaning I have viewController A which segued to viewController B. I dismissed viewController B and now back at viewController A. How can I go back to the same instance of viewController B?
I've looked at a lot of SO posts but they all seemed to be about unwinding, which would work if I want to go from B back to A, but not back to B again.
Also, viewController A is in a tabbar. Viewcontoller B is not.
Thanks!
You can't do this with a segue, since segues always instantiate new controllers. Instead of a segue, you should create a property for ViewControllerB in ViewControllerA, and instantiate it only the first time you go to it (which you would do using presentViewController:animated:completion). After coming back to A, when you want to go to B again present the instance you already created. If you're using a storyboard to make your controllers, you would do something like this,
-(void)someMethod {
if (!self.vcB) { // vcB is a strong property
self.vcB = [self.storyboard instantiateViewControllerWithIdentifier:#"VCB"];
}
[self presentViewController:vcB animated:YES completion:nil];
}
You will want to create a reference to VC B:
var VCB:UIViewController = bInstance
Then you will want to dismiss VCB from VCA
VCA.dismissViewController(VCB,animated:false)
Then to bring it back you go:
VCA.presentViewController(VCB,animated:false)
Keep in mind that the new compiler for Xcode uses ARC which does automatic reference counting. You need to keep a reference to the UIViewController to bring it back, otherwise it gets deleted!
I have 3 View Controllers, conveniently named A, B, C.
A is presented using a UINavigationController, and has a push segue to C.
My desired effect is that after performing the segue, C's back button will pop us into B, and then B's back button pop us to A. Effectively, this means that segueing to C will put both B and C onto the stack.
in iOS7, I've used the following (redacted) code successfully:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
CViewController *slotViewer = segue.destinationViewController;
/* Do Stuff */
BViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"B"];
[self.navigationController pushViewController:controller animated:NO];
}
The result appearance was a smooth transition from A to C, while B is loaded and B's ViewWillAppear is only called when clicking on C's back button.
However, on iOS8, this breaks: The transition briefly flashes B on the screen, its viewWillAppear is called, and only then C is shown.
Any idiomatic way to perform this transition in iOS8?
I know I can use the method described here but it feels awkward, and I'd rather use the Segues all the way.
The method (setViewControllers) you linked was designed to do exactly you want. Why is it awkward? It's provided by Apple.. Besides that there is no way to use segues only. Your previous solution was same like pushing first one programatically and right after second one by interface builder..this is awkward man:).
Please don't do this. You're not supposed modify the navigation stack like that! It's awkward.
I have the following situation:
view controller A -> presents modally -> view controller B
view controller B -> presents modally -> view controller C
I would like to dismiss view controller "C" and go directly to "A" instead of showing "B" since it do not make sense to show "B" at that time.
How can I accomplish that ?
Thanks,
Daniel
In 'view controller C' ->
Before iOS 6:
Use
[self.parentViewController.parentViewController dismissModalViewControllerAnimated:YES];
Or,
[self.presentingViewController.presentingViewController dismissModalViewControllerAnimated:YES];
From and Above iOS 6:
Use
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
You can use segues to present view controllers from other view controllers.
To go backwards through a hierarchies you normally dismiss presented view controllers or you go back to specific view controllers through unwind segues.
Try the following:
[vcB dismissModalViewControllerAnimated:NO] //no Animation, so happens instantly
[vcA dismissModalViewControllerAnimated:YES] //with Animation, this is all you see
Your best bet would be use navigation controllers if your B and C are related and are more detailed version of A
A->B-C . You unwindsegue to unwind the stack/pop the view controllers pushed on the stack.
Read this link very useful - http://chrisrisner.com/Unwinding-with-iOS-and-Storyboards
This is an old question and has an accepted answer but it did not solve my problem. Therefore, I would like to propose another solution for those who need different approaches.
The story is A presents B, B presents C, A is shown when C is dismissed.
Here is my approach;
Present ViewB from ViewA, when it comes to presenting ViewC from ViewB, do it from ViewA, and dismiss ViewB as follows;
let presentingNavCon = navigationController?.presentingViewController as? UINavigationController
let viewC = ViewC()
navigationController?.dismiss(animated: false)
presentingNavCon?.present(viewC, animated: true)
so, when you dismiss ViewC, ViewA appears.
Supposedly I have a UIViewController A and a UIViewController B. From A, I call the method presentViewController:B. When B shows up, what happens to A? Is it removed from the memory? If not, what method should I call to delete it?
If my UI flow is like this, A->B->A->B->A->B->... and so on, how to prevent the memory from increasing accordingly?
When you use the presentViewController:animated:completion: method from controller A to present controller B modally, what happens is that the presentedViewController property of A is set to controller B, and the presentingViewController property of B is set to A. Thus, both controllers are kept in memory while the presentation is taking place.
When you go from B to A, you call dismissViewControllerAnimated:completion: on A via the presentingViewController property of B, like this:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
(You can also call [self dismissViewControllerAnimated:YES completion:nil] and the system will automatically forward the request to the presenting view controller.)
After that, the presentedViewController property of A will be set to nil and, consequently, it will be subject to memory deallocation by the system, provided that there isn't any other strong pointer pointing to it.
No, A won't be removed from memory.
And if you want to alternate between A and B you can either:
use a UINavigationController and push B, then pop it off again and you're back at A
or make B the new root controller of your window and then A again and add a proper transition
or use a as the root and present B. Then dismiss B and you're back at A.
The UIViewController will stay in memory unless you popped it.
Use push & pop instead of just pushing new UIViewControllers.
Instead of this A->B->A->B->A->B->
You'll get this A<->B
Have a root view controller when ever A completes it's task let your root view is responsible of removing A and and presenting B. Like wise when B finishes its task alert your root view to remove B and show A again.
It won't be released automatically. You can release it manually by using dismissModalViewControllerAnimated.
Here is a very good tutorial to see this : Link