I have REAL misunderstanding with MFMailComposeViewController in Swift (iOS8) in Simulator
* * IMPORTANT - DO NOT USE THE SIMULATOR FOR THIS. * *
Even in 2016, the simulators very simply do not support sending mail from apps.
Indeed, the simulators simply do not have mail clients.
But! Do see the message at the bottom!
Henri has given the total answer. You MUST
-- allocate and initiate MFMailComposeViewController in an earlier stage, and
-- hold it in one static variable, and then,
-- whenever it's needed, get the static MFMailComposeViewController instance and use that.
AND you will almost certainly have to cycle the global MFMailComposeViewController after each use. It is not reliable to re-use the same one.
Have a global routine which releases and then re-initializes the singleton MFMailComposeViewController
. Call to that global routine, each time, after you are finished with the mail composer.
Do it in any singleton. Don't forget that your app delegate is, of course, a singleton, so do it there...
@property (nonatomic, strong) MFMailComposeViewController *globalMailComposer;
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
........
// part 3, our own setup
[self cycleTheGlobalMailComposer];
// needed due to the worst programming in the history of Apple
.........
}
and...
-(void)cycleTheGlobalMailComposer
{
// cycling GlobalMailComposer due to idiotic iOS issue
self.globalMailComposer = nil;
self.globalMailComposer = [[MFMailComposeViewController alloc] init];
}
Then to use the mail, something like this ...
-(void)helpEmail
{
// APP.globalMailComposer IS READY TO USE from app launch.
// recycle it AFTER OUR USE.
if ( [MFMailComposeViewController canSendMail] )
{
[APP.globalMailComposer setToRecipients:
[NSArray arrayWithObjects: emailAddressNSString, nil] ];
[APP.globalMailComposer setSubject:subject];
[APP.globalMailComposer setMessageBody:msg isHTML:NO];
APP.globalMailComposer.mailComposeDelegate = self;
[self presentViewController:APP.globalMailComposer
animated:YES completion:nil];
}
else
{
[UIAlertView ok:@"Unable to mail. No email on this device?"];
[APP cycleTheGlobalMailComposer];
}
}
-(void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError *)error
{
[controller dismissViewControllerAnimated:YES completion:^
{ [APP cycleTheGlobalMailComposer]; }
];
}
{nb, fixed typo per Michael Salamone below.}
Have the following macro in your Prefix file for convenience
#define APP ((AppDelegate *)[[UIApplication sharedApplication] delegate])
Also here's a "minor" problem which can cost you days: https://stackoverflow.com/a/17120065/294884
Just for 2016 FTR here's the basic swift code to send an email IN APP,
class YourClass:UIViewController, MFMailComposeViewControllerDelegate
{
func clickedMetrieArrow()
{
print("click arrow! v1")
let e = MFMailComposeViewController()
e.mailComposeDelegate = self
e.setToRecipients( ["help@smhk.com"] )
e.setSubject("Blah subject")
e.setMessageBody("Blah text", isHTML: false)
presentViewController(e, animated: true, completion: nil)
}
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?)
{
dismissViewControllerAnimated(true, completion: nil)
}
However! Note!
These days it is crappy to send an email "in app".
It's much better today to simply cut away to the email client.
Add to plist ...
LSApplicationQueriesSchemes
instagram
and then code like
func pointlessMarketingEmailForClient()
{
let subject = "Some subject"
let body = "Plenty of email body."
let coded = "mailto:blah@blah.com?subject=\(subject)&body=\(body)".stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet())
if let emailURL:NSURL = NSURL(string: coded!)
{
if UIApplication.sharedApplication().canOpenURL(emailURL)
{
UIApplication.sharedApplication().openURL(emailURL)
}
else
{
print("fail A")
}
}
else
{
print("fail B")
}
}
These days, that is much better than trying to email from "inside" the app.
Remember again the iOS simulators simply do not have email clients (nor can you send email using the composer within an app). You must test on a device.
MFMailComposeViewController in iOS 8
You can define the app delegate in whichever ViewController you are working in, by using:
AppNameAppDelegate *APP = [[UIApplication sharedApplication]delegate];
To state the obvious, by AppName I mean the name of your application. Make sure to import the AppDelegate.h into your .m file too.
#import "AppNameAppDelegate.h"
For the record, I am also having the same issue with MFMailComposeViewController
,and I have tried the method suggested in the post you linked (creating a global mail composer), but it still won't work for me using the iOS 8 simulator. Apparently it works on a physical device running iOS 8, but I personally cannot confirm that just yet.
MfMailComposerViewController crash on ios8
Before to alloc and present the MFMailComposeViewController check if the device can send mails:
if ([MFMailComposeViewController canSendMail]) {
//your code here
}
MailComposer not dismissed
You are not supposed to use the same MFMailComposeViewController
instance again..
Try this
func setupMailer() {
if MFMailComposeViewController.canSendMail() {
emailController = MFMailComposeViewController.init()
emailController.mailComposeDelegate = self
emailController.setToRecipients([]) // set the email address
emailController.setSubject("BackgroundTask Test")
emailController.setMessageBody("Message body", isHTML: false)
}
}
Related Topics
How to Mimic the Bottom Sheet from the Maps App
Xcode 7 Error: "Missing iOS Distribution Signing Identity For ..."
@Property Retain, Assign, Copy, Nonatomic in Objective-C
How to Convert an Nsstring Value to Nsdata
What Kind of Leaks Does Automatic Reference Counting in Objective-C Not Prevent or Minimize
iOS Detect If User Is on an iPad
How to Export "Fat" Cocoa Touch Framework (For Simulator and Device)
How to Create .Ipa File Using Xcode
Uiview and Initwithframe and a Nib File. How to Get the Nib File Loaded
How to Determine Whether Code Is Running in Debug/Release Build
Drawing a Route in Mapkit in Ios
How to Iterate For Loop in Reverse Order in Swift
How to Load Gif Image in Swift
Swiftui | Using Ondrag and Ondrop to Reorder Items Within One Single Lazygrid
Getting All Cookies from Wkwebview
How to Create a Swift Date Object
Change Default Scrolling Behavior of Uitableview Section Header