I've a class that subclass NSObject with a function do display a MFMailComposeViewController. Here is the code :
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
mailController.mailComposeDelegate = self;
[mailController setSubject:#"Sample Subject"];
[mailController setMessageBody:#"Here is some main text in the email!" isHTML:NO];
[mailController setToRecipients:#[self.email]];
UITabBarController *tabbarController = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController;
UINavigationController *navigationController = tabbarController.selectedViewController;
[navigationController.topViewController presentViewController:mailController animated:YES completion:NULL];
Everything works well with this code. The problem is when I want to dismiss the MFMailComposeViewController. Sometime I get a crash, sometimes it just don't happens nothing. I've implemented the delegate function :
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
UITabBarController *tabbarController = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController;
UINavigationController *navigationController = tabbarController.selectedViewController;
[navigationController.topViewController dismissViewControllerAnimated:YES completion:nil];
}
After that I tried to show and dismiss it directlty from a ViewController and everything was working. Even the cancel button.
I don't know why it works in my ViewController Class but not in my subclass of NSObject.
When I get the crash I've seen in the logs :
-[MFMailComposeInternalViewController _notifyCompositionDidFinish]
Try this,
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
// Do your work and dismiss after you are done with it.
[controller dismissViewControllerAnimated:YES completion:nil];
}
Hope that helps.
Try this in your singleton class
UIViewController *currentViewController;
- (void)sendEmail:(id) viewController {
currentViewController=(UIViewController*)viewController;
NSString * appVersionString =#"";
NSString *strEmailMessage=#"";
NSString *strEmailSubject=#"";
NSArray *toRecipents =#"";
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate =viewController;
[mc setSubject:strEmailSubject];
[mc setMessageBody:strEmailMessage isHTML:NO];
[mc setToRecipients:toRecipents];
[viewController presentViewController:mc animated:YES completion:NULL];
}
else{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"Error" message:#"Please setup email account" delegate:nil cancelButtonTitle:#"cancle" otherButtonTitles:nil];
[alert show];
}
}
set delegate like this
mc.mailComposeDelegate =viewController;
to dissmiss viewController
- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
switch (result)
{
case MFMailComposeResultCancelled:
break;
case MFMailComposeResultSaved:
break;
case MFMailComposeResultSent:
break;
case MFMailComposeResultFailed:
break;
}
// Close the Mail Interface
[currentViewController dismissViewControllerAnimated:YES completion:NULL];
}
i hope this will work...
Related
This question already has answers here:
Objective C: Send email without leaving app
(3 answers)
Closed 3 years ago.
I want to send mail while clicking a button in a custom UITableViewCell using MFMailComposeViewController.
Appreciate if answer is in Objective-C.
Following code in your .h file
#import <MessageUI/MFMailComposeViewController.h>
Give Delegate <MFMailComposeViewControllerDelegate>
Following code in your .m file
//Where you want to open dialog write below code
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailCont = [[MFMailComposeViewController alloc] init];
mailCont.mailComposeDelegate = self; // Required to invoke mailComposeController when send
[mailCont setSubject:#"Your Subject!"];
[mailCont setToRecipients:[NSArray arrayWithObject:#"hello#test.com"]];
[mailCont setMessageBody:#"Your Body" isHTML:NO];
[self presentViewController:mailCont animated:YES completion:nil];
}
//Delegate Method
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
switch (result)
{
case MFMailComposeResultCancelled:
//YOUR ACTION
break;
case MFMailComposeResultSent:
//YOUR ACTION
break;
case MFMailComposeResultSaved:
//YOUR ACTION
break;
case MFMailComposeResultFailed:
//YOUR ACTION
break;
default:
break;
}
}
You can dismiss view by this code - [self dismissViewControllerAnimated:YES completion:nil];
Make sure you are testing it in Real device not in simulator and you have a mail ID configured in your device
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
#interface ViewController ()<MFMailComposeViewControllerDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)sendmail:(id)sender {
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:#"Subject"];
NSArray *toRecipients = [NSArray arrayWithObjects:#"Recipients", nil];
[mailer setToRecipients:toRecipients];
NSString *emailBody = #"Body";
[mailer setMessageBody:emailBody isHTML:NO];
[self presentViewController:mailer animated:YES completion:nil];
}
}
- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
// Close the Mail Interface
[self dismissViewControllerAnimated:NO completion:NULL];
}
This is a really weird issue! I have a button on screen which when pressed launches the MFMailComposeViewController using the following code:
-(IBAction) openComposeEmailScreen:(id) sender {
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailComposeViewController = [[MFMailComposeViewController alloc] init];
mailComposeViewController.mailComposeDelegate = self;
[mailComposeViewController setToRecipients:[NSArray arrayWithObject:#"johndoe#gmail.com"]];
[mailComposeViewController setSubject:#"HelloWorld"];
NSLog(#"%#",_pasteBoard.string);
[mailComposeViewController setMessageBody:_pasteBoard.string isHTML:NO];
[self presentViewController:mailComposeViewController animated:YES completion:nil];
}
}
-(void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
if(error) {
NSLog(#"%#",error.localizedDescription);
}
[self dismissViewControllerAnimated:YES completion:nil];
}
Also, my view controller uses the correct protocol:
ViewController ()<MFMailComposeViewControllerDelegate>
I am running this on the simulator.
MFMailComposeViewController isn't supported in the simulator. You have to run on a device.
I am a bit confused on how to display mail composer when I click the email option in UIActionSheet.
Here's my sample code:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex == 0)
{
NSString *emailTitle = #"Test Email";
NSString *messageBody = #"iOS programming is so fun!";
NSArray *toRecipents = [NSArray arrayWithObject:#"support#email.com"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:NO];
[mc setToRecipients:toRecipents];
[self presentViewController:mc animated:YES completion:NULL];
}
}
Make sure you add to your .h file and import the MessageUI.framework
Here is exactly what your looking for. I use this often. By the way UIActionSheets are deprecated in iOS 8. Here you go though:
.h
ViewController : UIViewController <MFMailComposeViewControllerDelegate>
.m
- (IBAction)showActionSheet:(id)sender {
UIActionSheet *moreActions = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Add To Favorites", #"Search",#"Email", nil];
[moreActions showInView:self.view];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0: [self addToFav:self];
break;
case 1: ; [self popSearchBar:self];
break;
case 2: { [self sendEmail];
break;
}
break;
}
}
- (void)sendEmail {
NSString *emailTitle = #"This is email title";
// Email Content as for HTML
NSString *messageBody = [NSString stringWithFormat:#"I may have found a missing document in your catalog. I tried opening :<p><strong><font color=\"red\"> %# </font><br>'%#'</strong></p> with no results. Can I have a dollar for reporting this?", self.title, self.titleString];
// To address
NSArray *toRecipents = [NSArray arrayWithObject:#"youremail#google.com"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:YES];
[mc setToRecipients:toRecipents];
// Present mail view controller on screen
[self presentViewController:mc animated:YES completion:NULL];
}
- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult: (MFMailComposeResult)result error:(NSError *)error
{
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"Mail cancelled");
[self dismissViewControllerAnimated:YES completion:NULL];
break;
case MFMailComposeResultSaved:
NSLog(#"Mail saved");
[self dismissViewControllerAnimated:YES completion:NULL];
break;
case MFMailComposeResultSent:
NSLog(#"Mail sent");
[self dismissViewControllerAnimated:YES completion:NULL];
break;
case MFMailComposeResultFailed:
NSLog(#"Mail sent failure: %#", [error localizedDescription]);
break;
default:
break;
}
// Close the Mail Interface
[self dismissViewControllerAnimated:YES completion:NULL];
}
Also note that some people are having issues with simulator emails. try it on a device before you give up.
Here's the code:
First add and import the message framework:
#import <MessageUI/MessageUI.h>
then mark your self as a delegate like this
#interface MYViewController () <MFMailComposeViewControllerDelegate>
then to pull up the composer:
- (IBAction)emailButtonPressed:(id)sender
{
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *composeViewController = [[MFMailComposeViewController alloc] initWithNibName:nil bundle:nil];
[composeViewController setMailComposeDelegate:self];
[composeViewController setToRecipients:#[#"example#email.com"]];
[composeViewController setSubject:#"example subject"];
[self presentViewController:composeViewController animated:YES completion:nil];
}
}
Then to handle the delegate callback and dismiss the composer:
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
//Add an alert in case of failure
[self dismissViewControllerAnimated:YES completion:nil];
}
in actionsheet using actionSheet: clickedButtonAtIndex:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
//Get the name of the current pressed button
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:#"Your button title"]) {
[self btnContact];
}
}
call this method
- (void)btnContact{
// Email Subject
NSString *emailTitle = #"";
// Email Content
NSString *messageBody = #"";
// To address
NSString *toRecp = #"";
NSArray *toRecipents = [NSArray arrayWithObject:toRecp];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:NO];
[mc setToRecipients:toRecipents];
// Present mail view controller on screen
[self presentViewController:mc animated:YES completion:NULL];
}
This is appcoda's code . Instead of index use the button's name to fire your mail option .
My webview opens up a specific URL, and I have it set up where if a user taps the search button, the following dialogue appears:
How do I allow a user to share the url string when they tap each respective button? This is what I have so far:
- (IBAction)shareButtonAction:(id)sender {
UIActionSheet *popup = [[UIActionSheet alloc] initWithTitle:#"Select Sharing option:" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:
#"Share via E-mail",
#"Share via iMessage",
nil];
popup.tag = 1;
[popup showInView:[UIApplication sharedApplication].keyWindow];
}
- (void)actionSheet:(UIActionSheet *)popup clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (popup.tag) {
case 1: {
switch (buttonIndex) {
case 0:
NSLog(#"lets share on email");
break;
case 1:
NSLog(#"lets share on iMessage");
break;
default:
break;
}
break;
}
default:
break;
}
}
Sharing by email and message is using the same framework, these is the steps:
Add the framework MessageUI into your project.
Import the header in your class: #import <MessageUI/MessageUI.h>
Implements the sharing code
Use MFMailComposeViewController to share by email:
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
[mailController setMailComposeDelegate:self];
[mailController setSubject:#"Your subject"];
[mailController setToRecipients:#[#"email1", #"email2"];
[mailController setMessageBody:#"Your body" isHTML:NO];
[self presentViewController:mailController animated:YES completion:nil];
}
// Then implement the delegate method
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self dismissViewControllerAnimated:YES completion:nil];
}
And MFMessageComposeViewController to share by message:
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init];
[messageController setMessageComposeDelegate:self];
[messageController setRecipients:[NSArray arrayWithObject:#"recipient"]];
[messageController setBody:#"Your body"];
[self presentViewController:messageController animated:NO completion:nil];
}
// Then implement the delegate method
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
[self dismissViewControllerAnimated:YES completion:nil];
}
I am new to xcode, and am wondering how to send email in an app! My code is below, but I keep getting the error "No visible #interface for 'jakem' declares the selector 'presentViewControllerAnimated:'". Is my code completely wrong? Or did I just forget to declare the selector, and how do I declare the selector? I have researched all over the internet for at least an hour, and nothing is working. Someone please help me!
-(IBAction)sendEmail{
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
[composer setMailComposeDelegate:self];
if ([MFMailComposeViewController canSendMail]) {
[composer setToRecipients:[NSArray arrayWithObjects:#"FrankMurphy.CEO#RomansXIII.com", nil]];
[composer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentViewController:composer animated:YES];
}
}
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
if(error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"error" message:[NSString stringWithFormat:#"error %#", [error description]] delegate:nil cancelButtonTitle:#"dismiss" otherButtonTitles:nil, nil];
[alert show];
[self dismissViewControllerAnimated:YES];
}
else {
[self dismissViewControllerAnimated:YES];
}
}
in .h header file....
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#interface SimpleEmailViewController : UIViewController <MFMailComposeViewControllerDelegate> // Add the delegate
- (IBAction)showEmail:(id)sender;
#end
in .m implementation file.....
- (IBAction)showEmail:(id)sender {
// Email Subject
NSString *emailTitle = #"Test Email";
// Email Content
NSString *messageBody = #"iOS programming is so fun!";
// To address
NSArray *toRecipents = [NSArray arrayWithObject:#"info#finetechnosoft.in"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:NO];
[mc setToRecipients:toRecipents];
// Present mail view controller on screen
[self presentViewController:mc animated:YES completion:NULL];
}
- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"Mail cancelled");
break;
case MFMailComposeResultSaved:
NSLog(#"Mail saved");
break;
case MFMailComposeResultSent:
NSLog(#"Mail sent");
break;
case MFMailComposeResultFailed:
NSLog(#"Mail sent failure: %#", [error localizedDescription]);
break;
default:
break;
}
// Close the Mail Interface
[self dismissViewControllerAnimated:YES completion:NULL];
}
Check if you are MFMailComposeViewControllerDelegate.
You do this like
#interface YouClassName : UIViewController <MFMailComposeViewControllerDelegate>
#end
I think you're using the wrong method. Try
[self presentViewController:(UIViewController *) animated:(BOOL) completion:(void)completion];
instead of:
[self presentViewController:composer animated:YES];
I work for Sendgrid. We have an Objective-c library that lets you quickly send email from inside your app, https://github.com/sendgrid/sendgrid-objc. You can use cocoapods to quickly install the library in your project.
Then sending the email from your (IBAction) would look like this:
-(IBAction)sendEmail{
sendgrid *msg = [sendgrid user:#"username" andPass:#"password"];
msg.to = #"FrankMurphy.CEO#RomansXIII.com";
msg.from = #"me#bar.com";
msg.text = #"hello world";
msg.html = #"<h1>hello world!</h1>";
[msg sendWithWeb];
}