I'm a software developer, and I'm making an application for the email message and I have the following code:
// Header file
// importing the MessageUI framework
#import <MessageUI/MessageUI.h>
// adding the delegate functionality to the class (<MFMailComposeViewControllerDelegate>)
#interface TutorialProjectViewController : UIViewController <MFMailComposeViewControllerDelegate> {
}
- (IBAction)pressTheMailButtonDudeFunction:(id)sender
// Implementation file
- (IBAction)pressTheMailButtonDudeFunction:(id)sender {
// allocatind new message composer window
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
// setting a delegate method to "self"
mc.mailComposeDelegate = self;
// pre-populating the message subject
[mc setSubject:#"Send me a message"];
// adding content of the message as a plain text
[mc setMessageBody:#"Send me a message is you like this tutorial :)" isHTML:NO];
// adding content of the message as an HTML
[mc setMessageBody:#"<p>Send me a message is you like this tutorial :)<p>" isHTML:YES];
// adding recipients
[mc setToRecipients:[NSArray arrayWithObjects:#"Fuerte <info#fuerte.cz>", #"info#xprogress.com", nil]];
// adding recipients for a send copy to (arrayWithObject or arrayWithObjects)
[mc setCcRecipients:[NSArray arrayWithObject:#"test#example.com"]];
// adding hidden recipients
[mc setBccRecipients:[NSArray arrayWithObject:#"test#example.com"]];
// adding image attachment
// getting path for the image we have in the tutorial project
NSString *path = [[NSBundle mainBundle] pathForResource:#"Extra_Xcode_100x100" ofType:#"png"];
// loading content of the image into NSData
NSData *imageData = [NSData dataWithContentsOfFile:path];
// adding the attachment to he message
[mc addAttachmentData:imageData mimeType:#"image/png" fileName:#"Collection"];
// setting different than the default transition for the modal view controller
[mc setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
/*
Modal view controllers transitions:
UIModalTransitionStyleCoverVertical => pops up from the bottom, default transition
UIModalTransitionStyleCrossDissolve => fade on the screen
UIModalTransitionStyleFlipHorizontal => page flip
*/
// displaying our modal view controller on the screen (of course animated has to be set on YES if you want to see any transition)
[self presentModalViewController:mc animated:YES];
// releasing the controller
[mc release];
}
// delegate function callback
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
// switchng the result
switch (result) {
case MFMailComposeResultCancelled:
NSLog(#"Mail send canceled.");
/*
Execute your code for canceled event here ...
*/
break;
case MFMailComposeResultSaved:
NSLog(#"Mail saved.");
/*
Execute your code for email saved event here ...
*/
break;
case MFMailComposeResultSent:
NSLog(#"Mail sent.");
/*
Execute your code for email sent event here ...
*/
break;
case MFMailComposeResultFailed:
NSLog(#"Mail send error: %#.", [error localizedDescription]);
/*
Execute your code for email send failed event here ...
*/
break;
default:
break;
}
// hide the modal view controller
[self dismissModalViewControllerAnimated:YES];
}
And I'm not getting the proper answer... Is it a right code?
Be sure that you included the MessageUI framework into your iOS project. Within Xcode 4, you can include the framework by selecting your project in the left column. Then selecting the Tab "Build Phases". Here you can click on the arrow left of "Link Binary With Libraries" and you see the list of frameworks which are already included to your app. If MessageUI.framework is missing - just add it there.
The code you posted looks like a complete tutorial code snipped ... so only use the code you need ... and add more features to it step by step. This way you'll see where you add a buggy line of code. Maybe there is no image "Extra_Xcode_100x100.png" in your app bundle.
So, here's a "minimal" MFMailComposeViewController:
- (IBAction)showMinimalModalMailView:(id)sender {
// get a new new MailComposeViewController object
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
// his class should be the delegate of the mc
mc.mailComposeDelegate = self;
// set a mail subject ... but you do not need to do this :)
[mc setSubject:#"This is an optional mail subject!"];
// set some basic plain text as the message body ... but you do not need to do this :)
[mc setMessageBody:#"This is an optional message body plain text!" isHTML:NO];
// set some recipients ... but you do not need to do this :)
[mc setToRecipients:[NSArray arrayWithObjects:#"first.address#test.com", #"second.address#test.com", nil]];
// displaying our modal view controller on the screen with standard transition
[self presentModalViewController:mc animated:YES];
// be a good memory manager and release mc, as you are responsible for it because your alloc/init
[mc release];
}
I had the same issue, every time ran the app on sending the message it crashed; I found that if I removed
[mc setToRecipients:[NSArray arrayWithObjects:#"first.address#test.com", #"second.address#test.com", nil]];
it works fine and just asks me for the email address.
For sending email message from the app your device should be configure for email service.
// importing the MessageUI framework
#import <MessageUI/MessageUI.h>
// adding the delegate functionality to the class (<MFMailComposeViewControllerDelegate>)
#interface ViewController : UIViewController <MFMailComposeViewControllerDelegate> {
}
- (IBAction)sendEMailClick:(id)sender {
//check mail service is configure to your device or not.
if ([MFMailComposeViewController canSendMail]) {
// get a new new MailComposeViewController object
MFMailComposeViewController * composeVC = [MFMailComposeViewController new];
// his class should be the delegate of the composeVC
[composeVC setDelegate:self];
// set a mail subject ... but you do not need to do this :)
[composeVC setSubject:#"This is an optional mail subject!"];
// set some basic plain text as the message body ... but you do not need to do this :)
[composeVC setMessageBody:#"This is an optional message body plain text!" isHTML:NO];
// set some recipients ... but you do not need to do this :)
[composeVC setToRecipients:[NSArray arrayWithObjects:#"first.address#test.com", #"second.address#test.com", nil]];
// Present the view controller modally.
[self presentViewController:composeVC animated:true completion:nil];
} else {
NSLog(#"Mail services are not available or configure to your device");
}
}
after email is send or cancel click in MFMailComposeViewController delegate methode of MFMailComposeViewControllerDelegate is call, so there you can check email send status.
#pragma mark - MFMailComposeViewControllerDelegate Methode.
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(nullable 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.description);
break;
}
// Dismiss the mail compose view controller.
[controller dismissViewControllerAnimated:true completion:nil];
}
Related
I'm in a bit of trouble, I've spent half a day working onto this issue I have with no major results after all deprecations in iOS6 and other issues. This iOS app, has a send email option when after pushing a button, the app takes a screenshot of my WebView, attaches it to the email and from there, have the normal options to cancel or send the email and return to the app. I made it to the part where the email pops up, and actually 2 issues here: one is that after pressing either cancel or send, the email view won't dismiss, the app is stuck in the email view. And the second issue I have is the image that gets attached is just a tiny icon (blue with an question mark just like it is not recognised or is missing...
Can someone please point me in the right direction as I feel like I'm going crazy. I've researched the net backwards and forwards with no luck. Many similar threads but different issues not exactly related to my issues unfortunately. Sorry, and thanks in advance.
Here is my code:
// in my LiveView.h file
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <MessageUI/MessageUI.h>
#import "CamSetup.h"
#interface LiveView : UIViewController < MFMailComposeViewControllerDelegate , ADBannerViewDelegate >
....
-(IBAction)shotAndSend:(id)sender;
// in my LiveView.m file:
- (void)mailComposer:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
NSLog(#"in didFinishWithResult:");
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"cancelled");
break;
case MFMailComposeResultSaved:
NSLog(#"saved");
break;
case MFMailComposeResultSent:
NSLog(#"sent");
break;
case MFMailComposeResultFailed: {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error sending mail",#"Error sending mail")
message:[error localizedDescription] delegate:nil
cancelButtonTitle:NSLocalizedString(#"test",#"test")
otherButtonTitles:nil];
[alert show];
break;
}
default: break;
}
[self dismissViewControllerAnimated:NO completion:Nil];
}
-(IBAction)shotAndSend:(id)sender
{
UIGraphicsBeginImageContext(_myWebView.frame.size);
[_myWebView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * imageData = UIImageJPEGRepresentation (image, 2.1);
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController * mailComposer = [[MFMailComposeViewController alloc] init];
mailComposer.mailComposeDelegate = self;
[mailComposer addAttachmentData:imageData mimeType:#"image/jpeg" fileName:#"attachment.jpeg"];
[mailComposer setSubject:#"A screenshot from my App"];
[mailComposer setToRecipients:[NSArray arrayWithObjects:#"123#yexample.com", nil]];
[self presentViewController: mailComposer animated:YES completion:NULL];
}
}
Your code isn't working because you have the wrong method. You have:
- (void)mailComposer:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
but it should be:
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
You need a delegate of your view that will dismiss that view for you. The fact that you don't see the log indicate you that you haven't implemented correctly the delegation protocol. Take a look at some example in the apple documentation.
I want to be able to send an email from my app, in which I have got that portion working. The problem is when I cancel sending an email (which is what I'm testing for now) the email part is dismissed but I'm left with a black screen which I can't seem to dismiss.
So this is what I have. I've created a class to handle the email part:
MailViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#interface MailViewController : UIViewController <MFMailComposeViewControllerDelegate>
#end
Implemented as follows:
#import "MailViewController.h"
#interface MailViewController ()
#end
#implementation MailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
if([MFMailComposeViewController canSendMail]){
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
[mailer setMailComposeDelegate:self];
[mailer setSubject:#"Subject"];
NSMutableArray *toArray = [[NSMutableArray alloc] initWithObjects:#"email#gmail.com", nil];
[mailer setToRecipients:toArray];
[self presentViewController:mailer animated:YES completion:nil];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Failuer" message:#"This device is unable to send emails" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
switch (result){
case MFMailComposeResultCancelled:
NSLog(#"Mail cancelled: you cancelled the operation and no email was sent");
break;
case MFMailComposeResultFailed:
NSLog(#"Mail failed");
break;
case MFMailComposeResultSaved:
NSLog(#"Mail saved");
break;
case MFMailComposeResultSent:
NSLog(#"Mail sent");
break;
default:
NSLog(#"Mail not sent");
break;
}
[controller dismissViewControllerAnimated:YES completion:nil];
}
#end
And all of this is shown from another view like so:
-(IBAction)sendMessage:(id)sender{
NSLog(#"Going to send an email....");
MailViewController *mail = [[MailViewController alloc] init];
[self.navigationController pushViewController:mail animated:YES];
}
So when I run all of this, the email program opens and I can do email stuff. I can select Cancel, then Delete Draft and the email program is removed. However, I'm left with a black screen which I can then select Back from the top navigation bar to return to the previous view.
I simply want the app to return to the view that shows the email program when an email is sent or cancelled (or whatever). I'm sure it's something simple I'm missing.
The problem is tat you are pushing a MailViewController and then dimissing, if you push you should pop the view controller.
MFMailComposeViewControllers should be presented modally, not pushed on the navigation stack. You also dont need a subclass, you can create an instance of MFMailComposeViewController directly:
-(IBAction)sendMessage:(id)sender{
NSLog(#"Going to send an email....");
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[self presentViewController:mail animated:YES completion:nil];
}
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
switch (result){
case MFMailComposeResultCancelled:
NSLog(#"Mail cancelled: you cancelled the operation and no email was sent");
break;
case MFMailComposeResultFailed:
NSLog(#"Mail failed");
break;
case MFMailComposeResultSaved:
NSLog(#"Mail saved");
break;
case MFMailComposeResultSent:
NSLog(#"Mail sent");
break;
default:
NSLog(#"Mail not sent");
break;
}
[controller dismissViewControllerAnimated:YES completion:nil];
}
There's a couple architecture questions I have, but first - the TL;DR version:
[self.navigationController popViewControllerAnimated:NO];
You could also choose YES for the boolean, but judging on your implementation, that wouldn't result in something nice. Put that in the delegate call for completion.
However, why not just have whatever's pushing MailViewController onto the stack handle the job of being the MFMailComposeViewControllerDelegate? You're doing nothing here that requires a completely new view controller be pushed onto the stack.
I have a button in my app, when press it, a MFMailComposerViewController will show up, and when the composer dismisses, a MBProgressHUD with a custom view will show to tell user whether the mail is sent successfully or not.
It works fine if I press send button in the composer, the mail will be sent, the composer will be dismissed and a HUD will show. However, if I press the cancel button in the composer view, the composer dismisses, but HUD doesn't show, and the app crashes.
Here are the Log of crash.
2012-02-02 22:49:34.821 App[5091:707] -[ViewController size]: unrecognized selector
sent to instance 0x319210
2012-02-02 22:49:34.831 App[5091:707] *** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[ViewController size]: unrecognized selector sent to instance 0x319210'
*** First throw call stack:
(0x340af8bf 0x342ff1e5 0x340b2acb 0x340b1945 0x340b27b8
0x3748cfa5 0xf051 0x203d1 0x37553f5b 0x374f393b 0x374f37bf
0x3746d81b 0x37472fb9 0x34bc4ba7 0x36ce3e8d 0x340822dd
0x340054dd 0x340053a5 0x30889fcd 0x37486743 0xe7a7 0xe74c)
terminate called throwing an exception
The ViewController is the controller that present the mail composer.
Here are some code I used:
-(void)showHUDWithMessage:(NSString *)msg
{
HUD = [[MBProgressHUD alloc]initWithWindow:self.window];
[self.window addSubview:HUD];
HUD.delegate = self;
UIImage *image;
NSString *labelTextToShow;
//Do something here
UIImageView *imageView = [[[UIImageView alloc]initWithImage:image]autorelease];
HUD.labelText = labelTextToShow;
HUD.customView = imageView;
HUD.mode = MBProgressHUDModeCustomView;
[HUD show:YES];
[HUD hide:YES afterDelay:3.0];
}
-(void)mailFriend:(id)sender
{
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc]init];
mailController.mailComposeDelegate = self;
[mailController setSubject:#"Mail Subject"];
NSString *emailBody = #"Message";
[mailController setMessageBody:emailBody isHTML:YES];
[self presentModalViewController:mailController animated:YES];
}
-(void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
NSString *msg;
switch (result) {
case MFMailComposeResultSent:
msg = #"Sent";
break;
case MFMailComposeResultFailed:
msg = #"Fail";
break;
case MFMailComposeResultCancelled:
msg = #"Cancelled";
break;
case MFMailComposeResultSaved:
msg = #"Cancelled";
break;
default:
break;
}
//Show HUD here
[self showHUDWithMessage:msg];
[self dismissModalViewControllerAnimated:YES];
[controller release];
}
Since if the mail is sent, the composer view can dismiss successfully, the HUD can also show correctly, I really don't know what's wrong here...
Thanks!
Most likely this is overreleasing memory issue. Enable NSZombie and test your app.
Couple of things:
Where have you created controller ? You are responsible to release objects that you own. You don't own controller object so don't release it:
[controller release]; // comment this line
in
-(void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
Next:
-(void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
NSString *msg = nil; // If result is not equal to any of the case statements then you want to pass nil to [self showHUDWithMessage:msg];
switch (result) {
case MFMailComposeResultSent:
msg = #"Sent";
break;
case MFMailComposeResultFailed:
msg = #"Fail";
break;
case MFMailComposeResultCancelled:
msg = #"Cancelled";
break;
case MFMailComposeResultSaved:
msg = #"Cancelled";
break;
default:
break;
}
//Show HUD here
[self showHUDWithMessage:msg];
[self dismissModalViewControllerAnimated:YES];
[controller release];
}
and MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc]init]; in -(void)mailFriend:(id)sender autorelease or release it later. Although this has nothing to do with issue you might have.
Remove all reference to MBProgressHUD and put a simple NSLog in your method. I'll bet my bottom dollar MB is causing this.
If not, memory management is my obvious second choice here. Comment out [controller release];
when I press the sendMail button, it will go to the mail button, but when I hit send or cancel it will not take me back to my application. Any suggestions?
-(IBAction)sendMail {
MFMailComposeViewController *mailComposer = [[[MFMailComposeViewController alloc] init] autorelease] ;
if ([MFMailComposeViewController canSendMail]) {
[mailComposer setToRecipients:nil];
[mailComposer setSubject:nil];
[mailComposer setMessageBody:#"Default text" isHTML:NO];
[self presentModalViewController:mailComposer animated:YES];
}
}
You need to set a delegate (generally the same view controller that presented the MFMailComposeViewController). Then when the user taps the Save or Cancel button the MFMailComposeViewController will call -mailComposeController:didFinishWithResult:error on the delegate. So set yourself as the delegate and define the following method:
#pragma mark -
#pragma mark MessageUI Delegate Methods
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error {
[controller dismissModalViewControllerAnimated:YES];
}
Add the following line below your mail composer initialization
mailComposer.mailComposeDelegate = self;//very important if you want feedbacks on what the user did with your email sheet.
Then implement the delegate method as Kenny suggested. You can use this method to take custom actions.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
{
//Do something, If you need to
}
break;
default:
break;
}
[self dismissModalViewControllerAnimated:YES];
}
Remember to conform to the delegate by adding
#interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate> { }
If you are still having trouble, You may visit the following tutorial where everything nicely explained:
http://blog.mugunthkumar.com/coding/iphone-tutorial-in-app-email/
This wonderful line:
mailComposer.mailComposeDelegate = self;
is what made it happen for days without knowing that was what went wrong.
And do not forget them:
# import <UIKit/UIKit.h>
# import <MessageUI/MessageUI.h>
# import <MessageUI/MFMailComposeViewController.h>
In addition to importing the MessageUI.framework in the project.
Verified in IOS5
I'm trying to incorporate MFMailComposeViewController in my app. When I present it modally, the send button works fine and the email is sent, which implies that the result sent to the delegate is right in that case.
Whereas when I tap the cancel button it hangs up the app. The log shows no errors either, just the screen goes dark and everything gets disabled. Apparently, the result is not being passed to the delegate (I checked it through logs). it appears that the
(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
is never called whenever the cancel button is pressed. Probably that's the reason why the actionsheet (Save draft, cancel, delete draft) is not displayed and therefore the app hangs in right there.
I'm using the exact code from Apple's sample apps (MailComposer), it works perfectly there, but somehow fails in mine. :(
Kindly help me if anyone has ever come across the same issue, and successfully resolved it.
My code:
-(IBAction)emailButtonPressed:(id)sender{
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil)
{
if ([mailClass canSendMail])
{
[self displayComposerSheet];
}
else
{
[self launchMailAppOnDevice];
}
}
else
{
[self launchMailAppOnDevice];
}
}
#pragma mark -
#pragma mark Compose Mail
-(void)displayComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Ilusiones"];
// Set up recipients
NSArray *toRecipients = [NSArray arrayWithObject:#"anam#semanticnotion.com"];
[picker setToRecipients:toRecipients];
// Attach a screenshot to the email
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *myData = UIImagePNGRepresentation(viewImage);
[picker addAttachmentData:myData mimeType:#"image/png" fileName:#"viewImage"];
// Fill out the email body text
NSString *emailBody = #"";
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"Result: canceled");
break;
case MFMailComposeResultSaved:
NSLog(#"Result: saved");
break;
case MFMailComposeResultSent:
NSLog( #"Result: sent");
break;
case MFMailComposeResultFailed:
NSLog( #"Result: failed");
break;
default:
NSLog(#"Result: not sent");
break;
}
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark -
#pragma mark Workaround
-(void)launchMailAppOnDevice
{
NSString *recipients = #"mailto:anam#semanticnotion.com.com?cc=second#example.com,third#example.com&subject=illusions!";
NSString *body = #"&body=xyz";
NSString *email = [NSString stringWithFormat:#"%#%#", recipients, body];
email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}
Method
(void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error
is never called because you don't press any UIActionSheet button after cancelling, as it doesn't show on screen.
The reason this is happening is that the UIActionSheet appears off-screen. If you check the debug log you'll probably see a message saying Presenting action sheet clipped by its superview. Some controls might not respond to touches. On iPhone try -[UIActionSheet showFromTabBar:] or -[UIActionSheet showFromToolbar:] instead of -[UIActionSheet showInView:]."
That's why you see your view getting darker, but no UIActionSheet appears.
In my case, the problem was that my app is universal, but for some reason there was only one MainWindow.xib, and it was larger than the iPhone screen size (it was, in fact, the iPad screen size).
The solution is to create another MainWindow-iPhone.xib with the right dimensions and change the Info.plist entries called Main nib file base (iPad) and Main nib file base (iPhone) so that they point to the right file. Problem solved!
Hope it helps.
I had the same problem,commented out '[picker release];', and it worked fine! Explanation? I have none.
Msoler has it right, teh action sheet is displayed off-screen.
The MFMailComposeViewController display the action-sheet at x:y 0:0, so you have to make sure teh calling controller frame is at 0:0. I had a similar issue when I tried to display the MFMailComposeViewController from a view that was embedded in a scroll view.
I have implemented the same code . It works absolutely fine. When you click on the delete draft button,didFinishWithResult method is called and the mail is cancelled.
Be sure that you use the correct method,
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
I had a some what similar method implemented which was never called. I have no idea what I exactly had but the compiler did not give me a warning or error message.
Just in case anybody else makes the same mistake as I did... I implemented the mailComposeController:didFinishWithResult:error: method in my Swift code. It worked for a while but after several refactorings I noticed that it was suddenly not being called anymore. Eventually I noticed that the method had taken this form in my code:
private func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
}
So, as you can see I was a little bit too eager about privatizing my methods: Since the method is marked #optional in the MFMailComposeViewControllerDelegate you do not have to implement it. And while I actually had implemented it, the private modifier from there on hid the implementation - thus, from outside the file it seemed that the method was actually not implemented, at all! However, since the method was optional, the compiler did not complain...
To conclude: Do not mark optional delegate with the modifier private.
I have been wondering ever since learning Swift why there are no optional methods anymore - now I might have understood ;-).