After sending an in App email with photo attachment the Email window won't dismiss even when I hit send or cancel - iphone

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.

Related

SMS window wont dismiss objective-C

Hi I'm trying to make a SMS native extension for adobe AIR.
I Havnt coded in objective-c before but everything works fine except for the fact that the SMS window won't close when pressing send or cancel. Below is the main section of code but ask me if you need any more info. Thanks for reading.
also why is xcode telling me :"Method in protocol not implemented" for the second line ?
#import "SMSComposerHelper.h"
#implementation SMSComposerHelper
//Event name
static NSString *event_name = #"SMS_COMPOSER_EVENT";
-(void) sendSMS:(NSString *)toRecipient
messageBody:(NSString *)messageBody
{
FREDispatchStatusEventAsync(context, (uint8_t*)[event_name UTF8String], (uint8_t*)[#"WILL_SHOW_MAIL_COMPOSER" UTF8String]);
MFMessageComposeViewController *smsComposer = [[MFMessageComposeViewController alloc] init];
smsComposer.messageComposeDelegate = self;
//make string into array
NSArray *recipientArray;
recipientArray = [NSArray arrayWithObjects: toRecipient, nil];
smsComposer.body = messageBody;
smsComposer.recipients = recipientArray;
//show sms composer
[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentModalViewController:smsComposer animated:YES];
}
// Dismisses the sms composition interface when users tap Cancel or Send.
-(void) smsComposeController: (MFMessageComposeViewController*)controller didFinishWithResult: (MessageComposeResult)result error:(NSError*)error
{
NSString *event_info = #"";
// Notifies users about errors associated with the interface
switch (result)
{
case MessageComposeResultCancelled:
event_info = #"SMS_CANCELED";
break;
case MessageComposeResultSent:
event_info = #"SMS_SENT";
break;
case MessageComposeResultFailed:
event_info = #"SMS_FAILED";
break;
default:
event_info = #"SMS_UNKNOWN";
break;
}
FREDispatchStatusEventAsync(context, (uint8_t*)[event_name UTF8String], (uint8_t*)[event_info UTF8String]);
FREDispatchStatusEventAsync(context, (uint8_t*)[event_name UTF8String], (uint8_t*)[#"WILL_HIDE_SMS_COMPOSER" UTF8String]);
context = nil;
//hide mail composer
[[[[UIApplication sharedApplication] keyWindow] rootViewController] dismissModalViewControllerAnimated:YES];
}
-(void)setContext:(FREContext)ctx {
context = ctx;
}
#end
RESPONSE :
Omar thankyou so much for your answer and for answering so quickly!
First I tried your solution of using
[controller dismissModalViewControllerAnimated:YES];
but this did nothing so I changed it back.
My header already was :
#interface SMSComposerHelper : NSObject<MFMessageComposeViewControllerDelegate> {
So I decided to focus on fixing the warning.
The warning was solved by changing :
-(void) smsComposeController: (MFMessageComposeViewController*)controller didFinishWithResult: (MessageComposeResult)result error:(NSError*)error
to:
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
I would love to know why this worked ? do you know Omar ?
So I solved the warning but it still didn't dismiss.
So I tried your suggestion again:
[controller dismissModalViewControllerAnimated:YES];
AND IT WORKED !!!!
thanks so much man. You don't know how many hours I was stuck for.
I will be happy to accept your answer.
Instead of
[[[[UIApplication sharedApplication] keyWindow] rootViewController] dismissModalViewControllerAnimated:YES];
write
[controller dismissModalViewControllerAnimated:YES];
Also for the warning
Go to SMSComposerHelper.h
And add the following
#interface SMSComposerHelper : UIViewController<MFMessageComposeViewControllerDelegate>{
instead of
#interface SMSComposerHelper : UIViewController{

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

Sending email message from the app using MFMailComposeViewController in MessageUI on iPhone

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

iPhone In App Email Issue

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

Action sheet doesn't display when the MFMailComposeViewController's cancel button is tapped

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 ;-).