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

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.

Related

MFMailComposeViewController loads after delay if the "setToRecipients" method is called

I'm using MFMailComposeViewController and if I setup the recipients(setToRecipients), I can see 1-2 seconds delay between presenting the controller and the moment the data is loaded (at first an empty controller is presented, then the subject, body and recipients are loaded). It also causes that the navbar appearance settings is reloaded (tintColor).. It is noticeable only on simulator, but on device it happens as well, only it's faster so I can see the reloaded navbar settings.
Code:
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailer = [MFMailComposeViewController new];
mailer.mailComposeDelegate = self;
// content
[mailer setSubject:self.mailSubject];
[mailer setMessageBody:self.mailBody isHTML:NO];
[mailer setToRecipients:#[#"asdf#asdf.com"]];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:mailer animated:YES completion:nil];
});
}

ios : sms message composer not showing

I have a UITableViewController presenting a list of contacts, when the user selects a row, it'll show a UIActionSheet to ask the user an action (call, send sms...).
The user selects an action, and that first UIActionSheet will show another UIActionSheet which contains phone numbers.
The user selects a phone number, and this should show the SMS message composer.
The problem is that when the user selects a phone number, the message composer view doesn't show (just a black screen), and I receive the MessageComposeResultCancelled in the MFMessageComposeViewController's didFinishWithResult.
Which generates this warning "Warning: Attempt to dismiss from view controller while a presentation or dismiss is in progress!"
How can I correctly call and show the SMS message composer?
(this works perfectly if I call it directly when the user selects a row in the list with didSelectRowAtIndexPath)
Here's some code :
1- call to first UIActionSheet in didSelectRowAtIndexPath method :
UIActionSheet *popupQuery;
...
[popupQuery showInView:self.view];
2- call to second UIActionSheet in clickedButtonAtIndex method :
UIActionSheet *popupQuery2;
...
[popupQuery showInView:self.view];
3- from the same method, call to message composer :
[self sendSMS:#"" recipientList:[phoneNumbers objectAtIndex:buttonIndex]];
the method that shows message composer :
(void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
{
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if([MFMessageComposeViewController canSendText])
{
controller.body = bodyOfMessage;
controller.recipients = recipients;
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}
}
solution found here : MFMessageComposeViewController shows blank/white screen
controller.recipients = [NSArray arrayWithObject:theRecipients];
theRecipients was an array containing only one element (the phone number selected)
As you don't want to try showing two modal controls in the same time, use actionSheet:didDismissWithButtonIndex: delegate method so that action sheet is hidden when you start to show messaging controller.
The following code shows composer which is not cancelled automatically.
I can see 0 at log which is the value of MessageComposeResultCancelled, only when I press Cancel button. Are you trying to make a hack by pressing send button automatically ?
MFMessageComposeViewController.h
enum MessageComposeResult {
MessageComposeResultCancelled, //0
MessageComposeResultSent, //1
MessageComposeResultFailed //2
};
MyViewController.m
-(IBAction)onButtonPressed:(id)sender {
UIActionSheet * sheet = [[UIActionSheet alloc] initWithTitle:#"Title"
delegate:self
cancelButtonTitle:#"Go out"
destructiveButtonTitle:#"Show message composer"
otherButtonTitles:nil, nil];
[sheet showInView:self.view];
}
-(void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if([MFMessageComposeViewController canSendText])
{
controller.body = #"body";
// controller.recipients = recipients;
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}
}
-(void) messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
NSLog(#"%d", result);
[controller dismissModalViewControllerAnimated:YES];
}

Present MFMailComposeViewController from modal FormSheet on iPad?

Has anyone been successful showing the standard Apple MFMailComposeViewController from a UIModalPresentationStyleFormSheet view controller on the iPad?
When I do this the view shows as expected but when the user taps any of the input text views, the subject for example, and the keyboard slides pressing the Cancel button will show the "Delete Draft" & "Save Draft" popover outside of the screen bounds.
If I change the modal view to full screen it works properly.
I don't think you are presenting it as a Form Sheet then. Using this code works wonders for me:
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
[mailViewController setSubject:#"Subject"];
[mailViewController setMessageBody:#"" isHTML:NO];
mailViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:mailViewController animated:YES];

How to email the contents of a view

I have a view with a few text boxes and labels. I'd like to email the view containing this information to either a contact list or just a text box with an email address in it.
I can't get the view to email. I'd like to send the whole page without having to somehow list every text box. How do I email the view with this code:
[controller setMessageBody:textBoxesAndInfo isHTML:YES];
-(IBAction)sendMail {
// create an instance of MFMailComposeViewController for sending an e-mail
MFMailComposeViewController *controller =
[[MFMailComposeViewController alloc] init];
// set controller's delegate to this object
controller.mailComposeDelegate = self;
[controller setToRecipients:#[#"hello#example.com"]];
[controller setSubject:#"Subject"];
[controller setMessageBody:textBoxesAndInfo isHTML:YES];
// show the MFMailComposeViewController
[self presentModalViewController:controller animated:YES];
}
// called when the user finishes sending an e-mail
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self dismissModalViewControllerAnimated:YES];
}
Remember to include the MessageUI framework.

Release MFMAilComposeViewController after presentModalViewController: crashes

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.

Resources