Modal View's toolbar is obscured. MFMailComposeViewController - ios

I am trying to bring up an Email Window in my application, however the top toolbar that is suppose to have Cancel and Send is being obscured by the navigation controller.
I believe the reason is that I am calling
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setToRecipients:[NSArray arrayWithObject:#"internalapps#microstrategy.com"]];
[controller setSubject:#"Mobile HelpDesk App"];
[controller setMessageBody:#"" isHTML:NO];
if (controller){
[self presentViewController:controller animated:YES completion:^{}];
}
}
From a child ViewController that controls a view inside a scrollview (For Paging).
How do I get the toolbar to be on top of the navigation bar? Right now, it's only showing the new email window, but I cannot cancel or send the email.
I tried using [self.parentViewController presentViewController:controller animated:YES completion:^{}];, but that didn't do anything.
Thanks!

You can't use presentViewController:... from a view controller whose view isn't at the top of the view hierarchy (and so most likely doesn't occupy the whole screen). As you've seen, this results in a presented view which is perhaps partially visible and perhaps doesn't respond to touches in some areas.
Trying self.parentViewController is the correct solution (though the code you show is invalid). You need to ensure that you navigate far enough up the hierarchy to get to the 'root' view controller and present from there.

This sounds like it could be as simple as changing:
[self presentViewController:controller animated:YES completion:^{}];
to
[self.navigationController presentViewController:controller animated:YES completion:^{}];
Hope this helps you.

Related

MFMailComposeViewController wipes rootViewcontroller

Im making sending an email available for the user with this code:
MFMailComposeViewController *vc = [MFMailComposeViewController new];
[vc setSubject:#"Test Subject"];
[vc setMessageBody:#"Test Body" isHTML:NO];
[vc setMailComposeDelegate:self];
[self presentViewController:vc animated:YES completion:nil];
This opens a ViewController with all the stuff you need to sen an email, but it completely wipes everything from the ViewController the user is previously on. It only removes the subviews because the root view is still there because the backgroundColor is still the same.
I have already tried initWithRootViewController: but it crashes.
What is happening?
I found the bug... It wasn't in the code above. It seems the viewWillDissapear: is getting called when presenting the mailVC :/
In there I have code to remove every subview, so yeah, found the problem thanks anyways for those who answered and sorry for the inconvenience.
I'm not sure what you mean by "completely wipes everything". But suposing this is for iPad (and not iPhone), when presenting a view controller it goes full screen by default. If you want to change that, you have to set the modalPresentationStyle of the presented view controller (MFMailComposeViewController in your case)
Your code would look like this:
MFMailComposeViewController *vc = [MFMailComposeViewController new];
[vc setSubject:#"Test Subject"];
[vc setMessageBody:#"Test Body" isHTML:NO];
[vc setMailComposeDelegate:self];
vc.modalPresentationStyle = UIModalPresentationFormSheet; //You can use custom size too
[self presentViewController:vc animated:YES completion:nil];

how do I pop a view on a UIPageViewController?

I have a screen tutorial for my app. I have a UIPageViewController setup to manage 3 View Controllers. Once you get to the last view on the tutorial you press a "done" button and the tutorial is supposed to go away.
I can't seem to find a way to pop/dismiss the tutorial. I have tried the following:
[self dismissViewControllerAnimated:YES completion:nil];
[self.navigationController popViewControllerAnimated:YES];
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Any ideas would be appreciated.
The View Controllers being managed are subviews of UIViewController if that's of any help.
EDIT
This is how I set up the views:
In my UIPageViewController I have the following:
-(void)viewDidLoad{
[self.pageController setViewControllers:#[tutorialPages[0]]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
[self addChildViewController:self.pageController];
[[self view] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];
}
- (void)setupContentViews{
ScreenTutorial_1ViewController *screenTutorial1 = [[ScreenTutorial_1ViewController alloc] initWithNibName:#"ScreenTutorial_1ViewController" bundle:nil];
ScreenTutorial_2ViewController *screenTutorial2 = [[ScreenTutorial_2ViewController alloc] initWithNibName:#"ScreenTutorial_2ViewController" bundle:nil];
ScreenTutorial_3ViewController *screenTutorial3 = [[ScreenTutorial_3ViewController alloc] initWithNibName:#"ScreenTutorial_3ViewController" bundle:nil];
tutorialPages = #[screenTutorial1, screenTutorial2, screenTutorial3];
NSLog(#"tutorPages = %#", tutorialPages);
}
First, I strongly recommend you using:
[[NSUserDefaults standardUserDefaults] setObject:#YES forKey:#"hasSeenTutorial"];
Secondly, how are you presenting your PageViewController? In order to dismiss it like you have, you need to use (from a UIViewController):
[self presentViewController:tutorial animated:YES completion:nil];
Where tutorial is your Tutorial View controller. This will slide it up across the screen (or you can not animate it), and then you can dismiss it like you have.
Wild shot in the dark here, but I think you could reach your UIPageVieWController by calling self.parentViewController in your child controllers.
You could then either dismiss it (if it's modally presented) or pop it.
I just realized that I had 2 views in a xib file and the IBAction was connected to the wrong one. I've been copying and pasting buttons, labels...etc. On one of those pastes, I must have copied the pasted the entire view. I deleted it and used the following command which did dismiss the View:
[self dismissViewControllerAnimated:YES completion:nil];

Presentview(full screen) controller while dismissing View1 which is model view itself

I have an ipad app.
I am trying to open view 2 (kind of push view) full with entire screen. how normally do with push view or UIModalPresentationFullScreen. but my base view which is view 1 is also modal view.
so i was trying to open view 2 when view 1 get dismiss…
- (void) handleNewButton :(int)id
{
[self dismissViewControllerAnimated:YES
completion:^{
NewViewController *View2 = [NewViewController alloc] init];
View2.modalPresentationStyle = UIModalPresentationFullScreen;
View2.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController: View2 animated:YES completion:nil];
}];
}
but my view 2 is not opening. i know i can not do push view. But is there any way to achieve it?.
When you do this dismissViewControllerAnimated the UIViewController (self in this case) is gone, in the sense that he is not on the screen anymore, if it has been released or not, that's another story. The reason for you to not be able to show the View2 (very poor name, it should at least ViewController2) is because you are trying to show it from a UIViewController that is not on the screen anymore.
So, what can you do?
The current self in the context of the handleNewButton method, in theory was presented by another UIViewController, that's from where you want to present your View2.
Probably the quickest way of implementing of what I said, would probably be with a notification described here. Although I would do it with a block, so when the self would be created, I would pass a dismissiCompletionBlock that would be called when that UIViewController was dismissed.
try to allocate NewViewController with nib name if you are not using storyboard,
[self dismissViewControllerAnimated:YES
completion:^{
NewViewController *n=[[NewViewController alloc]initWithNibName:#"NewViewController" bundle:nil];
View2.modalPresentationStyle = UIModalPresentationFullScreen;
View2.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController: View2 animated:YES completion:nil];
}];
or if you are using storyboard get NewViewController using identifier.

Why UIActivityViewController doesn't dismiss MFMailComposeViewController when the presenter is a UITabbarController child?

I have a very simple case where a button shows an UIActivityViewController to share some content. The problem is that the mail composer is not dismissed when the user cancel or sends email.
NSArray *items = [NSArray arrayWithObjects:#"share",nil];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];
I tried to dismiss the modal view in the activityViewController.completionHandler but then the console says that another animation is in process and sometimes crash the app, so this isn't the solution. Besides other social networks work well (facebook, twitter) without doing anything.
After some tests I detected that this only occurs if the UIViewController that presents the UIActivityViewController is a child of a UITabBarController.
If in my AppDelegate I create the app like this it doesn't work:
UIViewController > UINavigationController > UITabbarController > Window
but if I remove the tabbar all works fine!:
UIViewController > UINavigationController > Window
A workaround that solves the problem is presenting from the rootviewcontroller.
[self.view.window.rootViewController presentViewController:activityViewController animated:YES completion:NULL];
but I want to know what's happening here.
Thanks! ;)
I had the same issue and after figuring out I get to know that when we don't present mail composer from the class which is currently active on window , it will fail to take responses some time like it will not get even present on every call, same is the problem with dismisal.
It is not that it is only the case with UITabbarController. It can happen to any architecture when you are presenting it from different controller which is not currently on window. That is why your workaround is working and its not wrong though.
I was presenting mail composer from a button tapped inside uipopover. Mail composer was being presented in that popover controller class. And I was facing the same issue you are facing. Then I changed my code to :
MFMailComposeViewController *mailComposer = [MFMailComposeViewController new];
[mailComposer addAttachmentData:data mimeType:#"application/pdf" fileName:model.documentTitle];
[mailComposer setSubject:model.documentTitle]; // Use the document file name for the subject
if(kBccEmailID)
[mailComposer setBccRecipients:[[NSArray alloc]initWithObjects:kBccEmailID, nil ]];
mailComposer.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
mailComposer.modalPresentationStyle = UIModalPresentationFormSheet;
AppDelegate *delagate =(AppDelegate *) [[UIApplication sharedApplication]delegate];
mailComposer.mailComposeDelegate = [[(UINavigationController *)delagate.window.rootViewController viewControllers] lastObject]; // Set the delegate
[(UIViewController *)[[(UINavigationController *)delagate.window.rootViewController viewControllers] lastObject] presentViewController:mailComposer animated:YES completion:nil];
[(UIViewController *)[[(UINavigationController *)delagate.window.rootViewController viewControllers] lastObject] is an alternative for your 'self.view.window.rootViewController'.

Dismiss UIViewController after presenting another one

I'm developing a single view iOS 5.0+ app and I'm going to navigate throw my ViewControllers this way:
SearchViewController* search =
[[SearchViewController alloc] initWithNibName:#"SearchViewController"
bundle:nil];
[self presentViewController:search
animated:NO
completion:nil];
My question is, if I'm opening SearchViewController from HomeViewController, is HomeViewController dismissed after SearchViewController is shown?
I have a lot of UIViewControllers and I don't know if all of them will be on memory while user is navigating between them.
If You want to Present Only one Viewcontroller you can try like,
SearchViewController* search =
[[SearchViewController alloc] initWithNibName:#"SearchViewController"
bundle:nil];
[self dismissViewControllerAnimated:NO completion:^{
[self presentViewController:search
animated:NO
completion:nil];
}];
When you present a ViewController from another ViewController, they never get released from memory. To release them from memory you need to explicitly dismiss them.
The method presentViewController:animated:completion: sets the
presentedViewController property to the specified view controller,
resizes that view controller’s view and then adds the view to the view
hierarchy.
So you see you are getting a stack of ViewControllers and adding a View on top of another.

Resources