UINavigationController behave wrong after dimiss presented viewcontroller IOS - ios

I am now using the tabbar controller and the uinavigation controller, when I call the MFMailComposeViewController by presentviewcontroller, and dismissed by dismissviewcontrolleranimated, I swipe back and click to push the viewcontroller again I found the back button is disappear and the title is wrong.
Tab-> ViewController [A] (Navigation Controller Embed) -(PUSH)-> ViewController[B] (with back button) -(Present)-> MFMailComposeViewController -(Dismiss)-> Show ViewController[B] -(Swipe Back)-> ViewController [A] -(Push) -> ViewController[B] (back button is disappear and the title is wrong)
Even I press back instead of swipe back, I found that there is still some problem not behave as usual navigation push controller
Many thanks if anyone could help!
After all these, ViewController[B] pop/swipe back to ViewController[A] viewdidappear and viewwillappear function in ViewController[A] are not triggered.

I have the exact same flow in my app, but I don't have any problem with the nav bar getting messed up.
Here's how the view controller is created:
MFMailComposeViewController *mailVC = [[MFMailComposeViewController alloc] init];
The delegate is set:
mailVC.mailComposeDelegate = self;
The view controller is presented:
[self presentViewController:mailVC animated:YES completion:nil];
The view controller is dismissed in the delegate method which is called when the user presses the Cancel button in the nav bar:
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
[self dismissViewControllerAnimated:YES completion:nil];
}
Hope this helps.

Related

Dismiss Modal View Controller and Simultaneously Segue from Sending to Different View Controller in IOS

I launch a modal view controller VCM embedded in a Navigation controller from VC1.
The modal VC has a button to go to another View Controller, VC2.
if the user presses the button to go to VC2, I need to simultaneously dismiss the modal and also change the sending from VC1 to VC2. (It's important to dismiss the modal to get rid of it, so I don't have VCs accumulating on the stack.)
Here is the action method in the modal attached to the VC2 button.
- (IBAction)VC2ButtonPressed:(id)sender {
[self dismissViewControllerAnimated:true completion:nil];
//Above line works fine
[VC1 performSegueWithIdentifier:#"showVC2" sender:VC1];//No known class method error
}
I can dismiss the modal without any problem (first line) but can't figure out how to simultaneously segue to VC2. There is a storyboard segue in VC1 named 'showVC2' for what it's worth. I do not have any relevant class methods currently in the sending VC. Should I create a special class method? Or how can I invoke a method in the VC that launched the modal.
Edit:
I also tried:
[self.presentingViewController performSegueWithIdentifier:#"showVC2" sender:self];
This compiles but gives runtime error () has no segue with identifier 'showVC2''
I think this is because VC2 is embedded in a tabbarcontroller.
Edit2:
I tried putting code in completion handler as suggested by #Oscar but while code gets fired, VC2 does not load
[self dismissViewControllerAnimated:YES completion:^{
[self gotoVC2];
}];
new method
-(void)gotoVC2 {
LogDebug(#"gotoVC2 called");//DOES log to console
UIStoryboard *storyBoard = self.storyboard;
IDFeedVC *VC2 =
[storyBoard instantiateViewControllerWithIdentifier:#"vc2"];
[self presentViewController:VC2 animated:YES completion: nil];
}
Thanks for any ideas.

`dismissViewControllerAnimated: completion:" dismisses keyboard and not VC

I have a ViewController with an UISearchController inside (with a table view on it). I've added this line on didSelectRowAtIndexPath::
[self dismissViewControllerAnimated:YES completion:nil];
For some reason, the viewController isn't being dismissed and instead, the keyboard is being dismissed (the searchController becomes inactive), to dismiss the viewController I have to reselect a cell on the table (and then didSelectRowAtIndexPath: is being called twice).
Any idea why is it happening?
Thank you!
This is probably happening because UISearchController inherits from UIViewController and therefore the controller being dismissed in didSelectRow is actually the search controller.
Perhaps simply try dismissing twice so that it removes the search controller followed by your custom view controller:
[self dismissViewControllerAnimated:YES completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
Try to resigning keyboard first and then dismiss vc.

ModalView on the top of UITabBarController during app launch

I'm a bit lost trying to figure it out...
I have a tab bar based app with login screen at the start. Login screen should be done as Modal View Controller BEFORE tab bar controller appears.
The problem is that I can present it only in viewDidAppear: method of TabBarController. And user can see for half a second content of the UITabBarController. I've tried to move call to viewDidLoad: or viewWillAppear: but it logs an error in console: "whose view is not in the window hierarchy!". As far as I can understand you can only add ModalViewController when all child UIViewControllers of UITabBarController are loaded, ad that happens in viewDidAppear: delegate method.
Do you have any solution how to show login screen without showing TabBarController before?
I've tried 2 ways of displaying ModalViewController, both of them work in viewDidAppear: only
XIB file with login view and using presentViewController: code
self.loginController = [[LoginViewController alloc] init];
[self presentViewController:self.loginController animated:NO completion:nil];
Storyboard, modal segue and calling it from the code:
[self performSegueWithIdentifier:#"loginScreen" sender:self];
Instead of a modal, you might consider pushing the login screen onto a navigation stack. Inside viewWillAppear: you can just instantiate your login viewController and push it. You could also do it in viewDidLoad if you'd like.
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController pushViewController:yourInstantiatedLoginViewController animated:NO];
}

start 1 view controller 2 buttons that lead to 2 different view controllers

I have the first ViewController that has 2 buttons on it. One to go to ViewController1 when clicked and the other to go to ViewController2 when clicked. When i click the first button it takes me to ViewController1 but when i click the second button it goes to a black screen and gives the warning:
Warning: Attempt to present on while a presentation is in progress!
What am I doing wrong?
Here is my code:
-(IBAction)goToYourClosetViewController: (id)sender{
YourClosetViewController *closet = [[YourClosetViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:closet animated:YES completion:NULL];
}
-(IBAction)goToPlanOutfitViewController: (id)sender{
PlanOutfitViewController *planOutfit = [[PlanOutfitViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:planOutfit animated:YES completion:NULL];
}
Are you pressing the first button and then the second button in rapid succession by any chance?
If that's it then you need to disable your buttons while the modal presentation is in progress, and re-enable them in your completion blocks.
If not, then how are you displaying the first view controller? (The one that contains these 2 buttons)
You are probably trying open the second view controller before you close the first view controller. That's the kind of error message in such cases.
When you go back to your initial view controller from either first or second view controller, do this:
[FirstViewControllerInstance dismissModalViewControllerAnimated:YES];

Back to RootViewController from Modal View Controller

From Home view - my RootViewController - I open up 2 ViewControllers one after another as user progresses in navigation hierarchy like so:
1) SecondViewController is pushed by button connected in my Storyboard
2) ThirdViewController is presented modally
[self performSegueWithIdentifier:#"NextViewController" sender:nil];
So, the picture is: RootViewController -> SecondViewController -> ThirdViewController
Now in my ThirdViewController I want to have a button to go back 2 times to my RootViewController, i.e. go home. But this does not work:
[self.navigationController popToRootViewControllerAnimated:YES];
Only this guy goes back once to SecondViewController
[self.navigationController popViewControllerAnimated:YES];
How can I remove both modal and pushed view controllers at the same time?
I had a similar situation, where I had a number of view controllers pushed onto the navigation controller stack, and then the last view was presented modally. On the modal screen, I have a Cancel button that goes back to the root view controller.
In the modal view controller, I have an action that is triggered when the Cancel button is tapped:
- (IBAction)cancel:(id)sender
{
[self.delegate modalViewControllerDidCancel];
}
In the header of this modal view controller, I declare a protocol:
#protocol ModalViewControllerDelegate
- (void)modalViewControllerDidCancel;
#end
And then the last view controller in the navigation stack (the one that presented the modal view) should implement the ModalViewControllerDelegate protocol:
- (void)modalViewControllerDidCancel
{
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController popToRootViewControllerAnimated:YES];
}
This method above is the important part. It gets the presenting view controller to dismiss the modal view, and then it pops back to the root view controller. Note that I pass NO to dismissViewControllerAnimated: and YES to popToRootViewControllerAnimated: to get a smoother animation from modal view to root view.
I had the same requirement but was using custom segues between the view controllers. I came across with the concept of "Unwind Segue" which I think came with iOS6. If you are targeting iOS6 and above these links might help:
What are Unwind segues for and how do you use them?
http://chrisrisner.com/Unwinding-with-iOS-and-Storyboards
Thanks.
Assuming your AppDelegate is called AppDelegate, then you can do the following which will reset the rootviewcontroller for the app window as the view RootViewController
AppDelegate *appDel = (AppDelegate*)[[UIApplication sharedApplication] delegate];
RootViewController *rootView = [[RootViewController alloc] init];
[appDel.window setRootViewController:rootView];

Resources