Release MFMAilComposeViewController after presentModalViewController: crashes - ipad

I have the following block of code which works fine in the simulator and on most devices, on some devices however (all on the same iOS version 4.2.1) the app is crashing when it gets to the [mailComposer release] call, does anyone have any insight on why this would be happening?
MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];
mailComposer.mailComposeDelegate = self;
[mailComposer setSubject:[self.webView stringByEvaluatingJavaScriptFromString:#"document.title"]];
[mailComposer setMessageBody:[NSString stringWithFormat:#"Hello, \n\n Here is the link we discussed. \n %#", [self.webView.request URL]] isHTML:NO];
[self presentModalViewController:mailComposer animated:YES];
[mailComposer release];

I had this exact same problem and I really have NO idea why it would crash, because presentModalViewController is supposed to retain the view controller. After fighting with it, I finally just added a property on my view controller which retained the reference to the mfMailComposeViewController and it worked fine. :/
MFMailComposeViewController* mfMailComposeViewController;
#property (nonatomic, retain) MFMailComposeViewController *mfMailComposeViewController;
then..
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:subject];
[controller setBody:body];
self.mfMailComposeViewController = controller;
[controller release];

Ok so I managed to figure out what was causing my issue with the help of my new iPad 2.
The issue was caused by not having any mail accounts configured, simply adding
if ([MFMailComposeViewController canSendMail])
before I create and present the view prevents the crashing, in my else block I added an UIAlertView to let the user know they cannot access that feature without first configuring a mail account.

Related

Why calling MFMailComposeViewController deallocates the view that called it?

I have this simple function to write mail on ios 8.0, xcode 6.1. Nothing special, it ever worked till ios 8.0 said hello.
The function sendMail sends a mail when a button gets tapped (set via storyboard). I debugged it and the code seems ok, but it crashes with a EXC_BAD_ACCESS code=1 error whenever you're supposed to return back to the main app, like when you tap the send or dismiss button of the MFMailComposeViewController. It seems to me that my View, i mean the view calling the MFMailComposeViewController is deallocated when the MFMailComposeViewController is called, so that when it get dismissed, there's nothing to return on. Some ideas to solve the problem?
[The function didFinishWithResult is never reached: the crash happens before.]
EDIT: To be precise it crashes with bad_access if in the presentViewController i set animated to NO. If it is YES it complain about 'unbalanced calls to begin/end appearance transitions' and tapping send/dismiss does nothing (it not returns. The mail view is alive but tap button does nothing)
EDIT: I am right about the deallocation. He have the same problem but it does not seems to have a valid solution MFMailComposeViewController crash in iOS6 ARC
In my case Arc is turned off and i cannot turn it on for various reasons. The theory is confirmed by zombie instrument. It says 'An Objective-C message was sent to a deallocated 'View' object (zombie) at address: 0x14e01720'
View.h
included MFMailComposeViewControllerDelegate and imported
#import <MessageUI/MFMailComposeViewController.h>
View.m
-(IBAction)sendEmail:(id)sender{
NSString *mailDiretta=emailText.currentTitle;
composer = [[MFMailComposeViewController alloc] init];
[composer setMailComposeDelegate:self];
if ([MFMailComposeViewController canSendMail]) {
[composer setToRecipients:[NSArray arrayWithObjects:mailDiretta, nil]];
[composer setSubject:#"Infos"];
[composer setMessageBody:#"Write to me, dude!" isHTML:NO];
[composer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentViewController:composer animated:YES completion:NULL];
[composer release];
} else
[composer release];
}
// function below is never reached
- (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 completion:NULL];
} else {
[self dismissViewControllerAnimated:YES completion:NULL];
}
}
I would assume it's because you're releasing the composer before it finishes.
[composer release];
EDIT: How is this property initialized and why is it a property? Create it in the method and try. Also, your unbalanced calls are happening because you're animating a UIAlert at the same time you are animating the mail controller dismiss. Each needs to finish prior to prevent that message.
composer = [[MFMailComposeViewController alloc] init];
Try to remove the property and initialize in the function.
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
Make sure you added the delegate properly as well.
#import <MessageUI/MessageUI.h>
#interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate>
Set your delegate like this
composer.mailComposeDelegate = self;
For the unbalanced calls, rearrange your alert like this...
[self dismissViewControllerAnimated:YES completion:NULL];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"error"
message:[NSString stringWithFormat:#"error %#", [error description]]
delegate:nil cancelButtonTitle:#"dismiss" otherButtonTitles:nil, nil];
[alert show];
EDIT 2:
After seeing your comment about not being able to use ARC due to one class I would advice you to simply set a -fno-objc-arc compiler flag on that class and enable ARC across your project and make your life WAY easier.
Disable Automatic Reference Counting for Some Files

iOS 7.1 MFMailComposeViewController Error

I was coding a new iPhone App with iOS 7 and iOS 7.1 Beta 5.
Not iOS 7.1 released for everybody and my MFMailComposeViewController isn't working anymore.
This is my code:
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
[mail setSubject:#"Test"];
[mail setToRecipients:#[#"alexander#sn0wfreeze.de"]];
[mail setMessageBody:#"Test" isHTML:NO];
[mail setMailComposeDelegate:self];
[self presentViewController:mail animated:YES completion:nil];
Well I think that has to be a serious bug in iOS 7.1
What do you say?
I tried it again in a sample App, which could only present the mail view controller.
The Problem is that it doesn't allows the user to interact and it doesn't set the recipient and the message body. As you can see in my screenshot below:
EDIT:
In the simulator it works perfectly!
So please test it on a device
Greetings,
Alexander Heinrich
MFMailComposeViewController * mailim = [[MFMailComposeViewController alloc]init];
[mailim setMailComposeDelegate:self];
NSString * mailara =#"xxx#yandex.ru";
NSArray *emailArray = [[NSArray alloc]initWithObjects:mailara, nil];
[mailim setToRecipients:emailArray];
[mailim setSubject:#"Bilgi Almak Istiyorum"];
[self presentViewController:mailim animated:YES completion:nil];
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
[self dismissViewControllerAnimated:YES completion:nil];
}
I fixed the problem by restarting the iPhone.
Never came across with such problems before...
I hope this won't occur more often

iPad Mini crashing on modal segue

I am developing an app that runs on all the deployment target simulators (5.0-6.1) and on my iPhone 3GS, 4, 4S and a gen 2 iPad. I had the opportunity today to try running it on an iPad Mini. I works everywhere except when I try to segue to a MFMailComposeViewController object to send an email, which causes it to crash with an exception.
I use the code directly from the MailComposer sample project, but it always crashes when it calls presentModalViewController:animated:. So I tried presentViewController:animated:completion: as the other method is deprecated, but it still doesn't work.
I linked to MessageUI.framework imported the classes:
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
The delegate is set. Here is the code:
-(void)displayComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Contact Email"];
// Set up recipient
NSArray *toRecipients = [NSArray arrayWithObject:#"info#foo.bar"];
[picker setToRecipients:toRecipients];
// [self presentModalViewController:picker animated:YES];
[self presentViewController:picker animated:YES completion:NULL];
}
Might there be a bug causing this in the iPad Mini? I don't have any other new devices I can try it on so I'm not sure if its a Mini problem or something bigger. Any help would be appreciated as I'm ready to submit to Apple but I sure don't want to do that with a crashing bug.
It's likely that a mail account has not been set up or for some other reason cannot send email.
Be sure to call the + (BOOL)canSendMail function of MFMailComposeViewController first.
Try wrapping your MFMailComposeViewController code with
if ( [MFMailCompseViewController canSendMail])
I'd guess the device doesn't have mail setup on it.

Why does trying to present an MFMailComposeViewController here lock up the screen?

I have an iPad application, composed of a root view controller that loads a second view controller. Within that second view controller, I have one button that should present an MFMailComposeViewController.
My Problem is:
On the Simulator, this works fine. However, on actual device, pressing this button locks up the screen and seems to disable all user interaction with the interface.
My Code is:
//************** Send Email using Default IM ************************
-(void) showEmailModalView
{
NSLog(#"Start method <ExportStatisticsController> : <showEmailModalView> --");
// emailTextField.text = [emailTextField.text stringByReplacingOccurrencesOfString:#"(null)" withString:#""];
// subjectTextField.text = [subjectTextField.text stringByReplacingOccurrencesOfString:#"(null)" withString:#""];
// messageBodyTextView.text = [messageBodyTextView.text stringByReplacingOccurrencesOfString:#"(null)" withString:#""];
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self; // <- very important step if you want feedbacks on what the
//user did with your email sheet
[picker setSubject:#""];
NSArray *torec=[[NSArray alloc] initWithObjects:#"xyz#company.com", nil];
[picker setToRecipients:torec];
[torec release];
//------ message body ---
NSString *body =#"";
[picker setMessageBody:body isHTML:NO]; // depends. Mostly YES, unless you want to send it as plain text (boring)
picker.navigationBar.barStyle = UIBarStyleBlack; // choose your style, unfortunately, Translucent colors behave quirky.
// picker.ModalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:picker animated:YES];
[picker release];
NSLog(#"End method <ExportStatisticsController> : <showEmailModalView> --");
}
What could I be doing wrong to cause a screen freeze like this?
The device is probably not set up to send mail.
Before using the MFMailComposeViewController you should call [MFMailComposeViewController canSendMail] to ensure that the device is configured to send mail.
It's probably a good idea too to check that your picker variable is non-nil before trying to present it as a modal view controller.

How can I send email using MFMailComposeViewController

I am very new to iPhone development.
In my app, I want to send email using MFMailComposeViewController while clicking a button.
How can I achieve this?
I used the code below.
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
[controller setSubject:#"Email App"];
[controller setMessageBody:#"Sample email app" isHTML:NO];
[self presentModalViewController:controller animated:YES]; // App crash in this line.
[controller release];
It is showing this warning:
'ImportingDocumentAppDelegate' may not respond to '-presentModalViewController:animated:'.
Thanks.....
#Arun presentModalViewController is the method of UIViewController so you cann't call it on app delegate instance. Add a UIViewController's view to your window then call this method on that view controller.
Your error message indicates that you are telling your app delegate to present the view. You need to call this function on a UIViewController.

Resources