I have a UIAlertView that launches an email and a messages screen. When a user clicks on the Alert's button, both views open, however, they do not close.
I have a tried adding:
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self dismissModalViewControllerAnimated:YES];
}
to the body of the class, however, it did not help.
Here is how the email is presented:
[viewController presentViewController:email animated:YES completion:nil];
Edit Here is the entire code I am using to present the email:
//send email...
-(void)sendEmail{
//mail composer
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if(mailClass != nil){
if([mailClass canSendMail]){
//get the current view controller from the App Delegate
apptester_appDelegate *appDelegate = (apptester_appDelegate *)[[UIApplication sharedApplication] delegate];
UIViewController *viewController = [appDelegate getViewController];
MFMailComposeViewController *email = [[MFMailComposeViewController alloc] init];
email.mailComposeDelegate = self;
//navigation bar color depends on iOS7 or lower...
if(floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1){
[[email navigationBar] setTintColor:[UIColor blackColor];
}else{
[[email navigationBar] setBarTintColor:[UIColor blackColor]];
}
//show the model view...
[viewController presentViewController:email animated:YES completion:nil];
}
}
}
Has anyone else experienced this error?
This may not be relevant, but this app has a tab bar.
Make sure you have set delegate for mail controller
mail.mailComposeDelegate = viewController;
Also try this as well,
[viewController.tabBarController presentViewController:email animated:YES completion:nil];
Have you try this method and pass "controller" instead of self:
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
[controller dismissViewControllerAnimated:YES completion:nil];
}
Thanks!
It is the responsibility of presenting controller to dismiss the modal view. Make sure you implement the delegate of the modal in the presenting controller.
Two things:
1) Make sure you set the mailComposeDelegate on the MFMailComposeViewController before you present it.
2) In your mailComposeController:didFinishWithResult:error: method, you should do:
[controller dismissModalViewControllerAnimated:YES];
Related
I am using MFMailComposeViewController in my application to compose a feedback E-Mail. The MFMailComposeViewController gets displayed, but can't be closed.
Method used to open the MFMailComposeViewController modal window:
-(IBAction) feedbackBtnClicked:(id)sender {
// Dismiss the Old View Controller
[self dismissViewControllerAnimated:NO completion:NULL];
// Present the New View Controller
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[mail setSubject:#"Sample Subject"];
[mail setMessageBody:#"Here is some main text in the email!" isHTML:NO];
[mail setToRecipients:#[#"example#mail.com"]];
[self presentViewController:mail animated:YES completion:NULL];
}
else
{
NSLog(#"This device cannot send email");
}
}
Here is what happens, when clicking on the buttons:
Senden (Send) - The E-Mail gets sent, but the modal window stays open; clicking on that button multiple times results in sending multiple E-Mails without the modal window ever getting closed.
Abbrechen (Cancel) - Nothing happens
How to dismiss make sure the MFMailComposeViewController gets dismissed after clicking on those buttons?
You need to implement the MFMailComposeViewControllerDelegate method mailComposeController:didFinishWithResult:error:, and dismiss the mail view controller…
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
I'm presenting an instance of CNContactViewController in my app. I want the user to be able to both edit the contact, as well as to dismiss this view controller. Below is the code to present the view controller, which is embedded in a UINavigationController. As you can see in the code, I have allowsEditing = YES, but looking at the screenshot; you can see that I'm not able to edit. Anyone able to help me see what I'm missing? Thanks!
CNContactViewController *contactController = [CNContactViewController viewControllerForUnknownContact:contact];
contactController.allowsEditing = YES;
contactController.delegate = self;
contactController.contactStore = store;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:contactController];
navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navController animated:YES completion:nil];
EDIT: I tried a different method suggested by #WrightCS:
[self presentViewController:contactController animated:YES completion:nil];
And, made sure to add this delegate method:
- (void)contactViewController:(CNContactViewController *)viewController
didCompleteWithContact:(CNContact *)contact{
[self dismissViewControllerAnimated:YES completion:nil];
}
But, repeatedly get this error log:
[CNUI ERROR] Contact view delayed appearance timed out
Instead of creating a UINavigationController instance, try presenting the contact controller directly.
[self presentViewController:contactController animated:YES completion:nil];
CNContactViewControllerDelegate
- (void)contactViewController:(CNContactViewController *)viewController
didCompleteWithContact:(CNContact *)contact;
Present on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:contactController];
navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navController animated:YES completion:nil];
});
The problem ended up being that I was initializing the CNContactViewController incorrectly...instead of:
CNContactViewController *contactController = [CNContactViewController viewControllerForUnknownContact:contact];
Which would display a contact, but not allow for the option of cancelling out of the contact view or editing it, the correct option (for my scenario) is to use
CNContactViewController *contactController = [CNContactViewController viewControllerForNewContact:contact];
I'm having trouble with removing a modal view.
I want to show (after pressing a button) a my own SendMailViewController which it self shows a MFMailComposeViewController. Then and after pressing cancel of send, in my own SendMailView controller in didFinishWithResult i do a [self dismissModalViewControllerAnimated:YES] and that works. The MFMailComposeView goes away.
But then the screen stays black....it think i also have to remove my SendMailViewController from it's parent. That's where i pushed the button...even after [self removeFromParentViewController] it still stays black...
Where do i go wrong?
And yes i would like the extra viewcontroller (SendMailViewController) because that controller will become the delegate of MFMailComposeViewController. Otherwise my caller (controller with the button) get's to much responsibility. Or do i also go wrong here?
Thanks,
/jr00n
- (IBAction)tapExportButton:(id)sender
{
SendMailViewController *sendMailController = [[SendMailViewController alloc]init];
[self presentViewController:sendMailController animated:YES completion:^() {[sendMailController openMailDialog];}];
[sendMailController release];
}
SendMailViewController:
- (void)openMailDialog
{
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
...
[self presentModalViewController:mailer animated:YES];
}
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
....
// Remove the mail view
// first i did this:
// [self dismissModalViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:^{[self removeFromParentViewController];}];
}
The problem is with the [self dismissViewControllerAnimated:YES completion:^{[self removeFromParentViewController];}]; in your didFinishWithResult method.
Remove that line and add the following line,
[controller dismissViewControllerAnimated:YES completion:^{[self dismissViewControllerAnimated:YES completion:nil]}];
That make sure we dismiss the controller after dismissing the MailController
I'm fairly new to this, so bear with me. I have 2 errors left to fix in my code. In both cases my instance methods are not found:
-(IBAction)goFlipSide {
NSLog(#"goFlipSide has been called:");
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil];
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:controller animated:YES];
[controller release];
}
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller {
[self dismissViewControllerAnimated:YES];
//This method gets fired when the user clicks done on the modal FlipsideViewController. This is different
//than the viewWillAppear.
self.navigationController.navigationBarHidden = TRUE;
/*
if (self.goViewSuccess == TRUE) {
//if the goViewSuccess boolean is set to YES - then we can load the load the goViewController
NSLog(#"goViewSuccess is YES");
[self loadGoViewController];
}
*/
}
Both instance methods not found are: presentViewController: and dismissViewControllerAnimated:.
What class is self? Those methods are only found on UIViewController. The full selectors are:
presentViewController:animated:completion:
dismissViewControllerAnimated:completion:
Try adding the completion block argument.
The code is supposed to be this
[self dismissViewControllerAnimated:YES completion:nil];
or if you want something when its done,
[self dismissViewControllerAnimated:YES completion:^{
//do stuff
}];
And for the other one
[self presentViewController:controller animated:YES completion:nil];
I have a View Controller which displays a table view. The VC calls another VC to display the send SMS view to the user, the code for this SMS VC is:
- (void) sendSMSWithBody: (NSString*) body andRecipients: (NSArray*) recipients
{
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if ([MFMessageComposeViewController canSendText])
{
controller.messageComposeDelegate = self;
controller.body = body;
controller.recipients = recipients;
[[UIApplication sharedApplication].delegate.window.rootViewController addChildViewController:self];
[self presentModalViewController:controller animated:YES];
}
}
- (void) messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
[self dismissModalViewControllerAnimated:YES];
[[UIApplication sharedApplication].delegate.window.rootViewController removeFromParentViewController];
}
(I know the call to sharedApplication is a bit hacky, but it will suffice for now. the rootViewController is a UINavigationController which has its root controller set to the table view controller)
I am invoking the SMS VC from the table VC like so:
- (void ) viewDidAppear:(BOOL)animated
{
static BOOL presentedSMSVC = NO;
if (!presentedSMSVC)
{
SendSMSController *sendSMS = [[SendSMSController alloc] init];
[sendSMS sendSMSWithBody:#"body"
andRecipients:[NSArray arrayWithObject:#"123456789"]];
presentedRegisterVC = YES;
}
}
The problem is that after the user sends the SMS the table view cells are not displaying.
I thought maybe I need to refresh the view/table so I added a protocol callback from the 2nd VC to the first which gets invoked when the user sends the SMS, and then within the callback call [self.tableView reloadData] But it made no difference.
So I got rid of the intermediary class and edited the table view to display the SMS view directly like this:
- (void ) viewDidAppear:(BOOL)animated
{
static BOOL presentedRegisterVC = NO;
if (!presentedRegisterVC)
{
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if ([MFMessageComposeViewController canSendText])
{
controller.messageComposeDelegate = self;
controller.body = #"body";
controller.recipients = [NSArray arrayWithObject:#"12345678"];
[self presentModalViewController:controller animated:NO];
}
}
}
- (void) messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
[self dismissModalViewControllerAnimated:NO];
}
But now the MFMessageComposeViewController doesn't dismiss (although messageComposeViewController:didFinishWithResult: does get called)
What is the problem with both approaches? Thanks
For the second variant, I changed to:
[self presentViewController: controller animated: YES completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
And that worked, haven't tried applying to the first method.
I faced a similar UI issue.
My case was: The controller, let's say controller A, in which I had written the code to present and dismiss the MFMessageComposeController, was not being used directly as the active controller rather I was using A.view as a subview over another controller, say controller B. So writing the following was distorting the view:
[self presentViewController:composeVC animated:YES completion:nil];
But then writing the following solved my issue:
[self.customTabbarNavigation presentViewController:composeVC animated:YES completion:nil];
The customTabbarNavigation, was the controller B, ans was actually the navigation controller which was active when controller A's view was visible.
Same change had to be made for dismissing the composeVC.