After hitting cancel in a MFMessageComposeViewController nothing happens - iphone

After though that after using MFMailComposeViewController the move to MFMessageComposeViewController was straight foward, but there is a catch.
Suppose this code:
MFMessageComposeViewController* mySMS = [[MFMessageComposeViewController alloc] init];
[mySMS setDelegate:self];
[self presentModalViewController:mySMS animated:YES];
It works this way for mails, but in sms you should set different the delegate to an internal structure like this:
[SMS setMessageComposeDelegate:self];
Hope you don not get stuck on this as I did early today.

You need to Implement the delegate method -(void)mailComposeController(MFMailComposeViewController*)controller didFinishWithResult (MFMailComposeResult)result error:(NSError*)error:
And inside it you should dismiss it yourself:
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
[self dismissModalViewControllerAnimated:YES];
}

You can see MFMailComposeResult in Apple documentation
enum MFMailComposeResult {
MFMailComposeResultCancelled,
MFMailComposeResultSaved,
MFMailComposeResultSent,
MFMailComposeResultFailed
};
typedef enum MFMailComposeResult MFMailComposeResult;
And you must dismiss controller by yourself in delegate method
- (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];
}

Related

sms window will not close after sending or cancelling sms

- (IBAction)SendTxt:(id)sender {
MFMessageComposeViewController *textComposer = [[MFMessageComposeViewController alloc] init];
[textComposer setMessageComposeDelegate:self];
if ([MFMessageComposeViewController canSendText]) {
[textComposer setRecipients:[NSArray arrayWithObjects:#"123456",#"123456", nil]];
[textComposer setBody:#"HELP ME"];
[self presentViewController:textComposer animated:YES completion:NO];
}
else {
NSLog(#"Can't open Text");
}
}
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
switch (result) {
case MessageComposeResultSent:
NSLog(#"SENT");
break;
case MessageComposeResultFailed:
NSLog(#"FAILED");
break;
case MessageComposeResultCancelled:
NSLog(#"CANCELLED");
break;
default:
break;
}
}
I have the above code which brings up the sms window as normal..
It works ok and sends a SMS but the SMS window will not close after sending or cancelling..
The NSLog registers the send or cancel but the SMS window will not go away!
Can anyone help?
Thanks
Mat
You have to dismiss it yourself using
[self dismissViewControllerAnimated:YES completion:^{ // something to do on completion if you need}];

Closing a view after cancelling an email

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.

App crashes when dismiss mail composer and show a HUD

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];

MFMailComposeViewController's delegate not handling the CANCEL button [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Action sheet doesn't display when the MFMailComposeViewController's cancel button is tapped
I've implemented standard mail functionality in my app according to the code sample provided by Apple.
I'm setting up the delegate as follows:
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
and I'm implementing
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
Hitting the Send button invokes the delegate and it all works fine. However, hitting the Cancel button doesn't call the delegate and it just dims the view; the app hangs right there.
After reading similar threads here, I've been thinking that the view could be off-screen for some reason which is beyond my comprehension at this point. Note that the view is being created programmatically and is not using a xib file.
Any thoughts or ideas ?
You need to implement mailComposeController:didFinishWithResult:error delegate. And in that you dismiss the view which is showing your mail view. If you have opened the mail view as a modalView, then the way to dismiss this is -
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error
{
if(error) NSLog(#"ERROR - mailComposeController: %#", [error localizedDescription]);
[self dismissModalViewControllerAnimated:YES];
return;
}
It may be helpful to you
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
//NSLog(#"Result: canceled");
break;
case MFMailComposeResultSaved:
//NSLog(#"Result: saved");
break;
case MFMailComposeResultSent:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Result" message:#"Mail Sent Successfully" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
break;
case MFMailComposeResultFailed:
//NSLog(#"Result: failed");
break;
default:
//NSLog(#"Result: not sent");
break;
}
[self dismissModalViewControllerAnimated:YES];
}
Try to add even simple delegate :
[picker setDelegate:self];

Using MFMailComposeViewController to send a mail, get “EXC_BAD_ACCESS” when dismissing the modal view controller

I am sending an email from my iPhone app using MFMailComposeViewController. This works fine but after sending or canceling I need to dismiss the modalViewController. When I do this I get a Program received signal: “EXC_BAD_ACCESS”. This is not very descriptive... Please help!!
This is the code for creating the mail and the modalViewController
-(void)sendFavMail:(NSString *)body{
MFMailComposeViewController* mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
[mailViewController setSubject:#"Favorites List"];
[mailViewController setMessageBody:body isHTML:YES];
[self presentModalViewController:mailViewController animated:YES];
[mailViewController release];
}
And this is the code for the delegate, dismissing the modalviewcontroller:
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error;
{
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"Cancelled sending");
break;
case MFMailComposeResultSaved:
NSLog(#"Message Saved");
break;
case MFMailComposeResultSent:
NSLog(#"Message Sent");
break;
case MFMailComposeResultFailed:
NSLog(#"Sending Failed");
break;
default:
NSLog(#"Message not sent");
break;
}
[self dismissModalViewControllerAnimated:YES];
}
Thanks for your help!!
Darn, fixed it myself :-)
I released an object in the body of the message before sending/cancelling. What I did to fix it is to declare this body object autoreleased. And what do you know? IT WORKS!
Just answered my own question...