ios: Application tried to present a nil modal view controller on target - ios7

I am developing an application,the requirement is to open email composer on a button click of UIAlertView.
message which is in message body of email is copied from UITextView. i am using following code snipt:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0)
{
// opening message composer
}
else
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Test mail"];
[picker setMessageBody:messageBody.text isHTML:YES];
[self presentViewController:picker animated:YES completion:NULL];
}
}
// mail compose delegate
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
but the issue is that i am getting error saying Application tried to present a nil modal view controller on target. how we can open default mail composer in ios 7?

As per Apple, You should check is MFMailComposeViewController are able to send your mail just before sending
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Test mail"];
[picker setMessageBody:messageBody.text isHTML:YES];
[self presentViewController:picker animated:YES completion:NULL];
}
Swift:
if MFMailComposeViewController.canSendMail() else {
// Send mail code
}
Ref : Apple Dev url

Swift 4 version
guard MFMailComposeViewController.canSendMail() else {
print("Mail services are not available")
return
}
sendEmail()

Forgetting Mail account configuration in device settings may also lead to this error. Re check whether a mail account is configured in your device or not.

Related

MFMessageComposeViewController does not show up send button and message body on ios8

MFMessageComposeViewController does not show up send button and message body on ios8, when tapping on recipient list keyboard comes up and also send button,message body shows up. Below is the code for message functionality :
MFMessageComposeViewController *msgController = [[MFMessageComposeViewController alloc] init] ;
if([MFMessageComposeViewController canSendText])
{
if (msgController)
{
msgController = nil;
msgController = [[MFMessageComposeViewController alloc] init] ;
}
NSString *messageBody =#"helloWorld";
msgController.body = messageBody;
msgController.recipients = numberArray;
msgController.messageComposeDelegate = (id)self;
[self presentViewController:msgController animated:YES completion:^{}];
Thanks in advance.
First of all add MessageUI framework to your app frameworks and then
#import <MessageUI/MessageUI.h>
#interface class()
<MFMailComposeViewControllerDelegate>
{
....
}
#end
Then in your class implementation write
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
[mail setMailComposeDelegate:self];
[mail setSubject:#"Subject goes here..."];
[mail setMessageBody:#"Message body goes here..." isHTML:NO];
[self presentViewController:mail animated:YES completion:NULL];
}
and also implement the delegate for MFMailcomposeViewController as like
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
[controller dismissViewControllerAnimated:YES completion:nil];
}
There should be recipient and some message in the body to enable the "Send" button.
Here is the link for reference:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/SystemMessaging_TopicsForIOS/Articles/SendinganSMSMessage.html#//apple_ref/doc/uid/TP40010416-SW1
http://iosdevelopertips.com/core-services/how-to-send-an-sms-progammatically.html
Hope this helps!

MFMailComposeViewController check if pressed send

Is there any way of checking if the user actually presses the send button when using the MFMailComposeViewController class?
Thanks
Use the MFMailComposeViewControllerDelegate (https://developer.apple.com/library/ios/documentation/MessageUI/Reference/MFMailComposeViewControllerDelegate_protocol/Reference/Reference.html)
-(void)sendMail
{
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
[mailer setMailComposeDelegate:self];
//do the rest of the mail composing
...
}
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
//don't forget to dismiss the controller
[controller dismissModalViewControllerAnimated:YES];
if(result == MFMailComposeResultSent)
{
//the user sent the mail
}
}

In App Email - MFMailComposeViewController - Error Message

My code is as follows:
ViewController.m:
#import "ViewController.h"
#import "MyScene.h"
#import "MainMenu.h"
#import <MessageUI/MessageUI.h>
#implementation ViewController
- (IBAction)showMailPicker:(id)sender
{
// You must check that the current device can send email messages before you
// attempt to create an instance of MFMailComposeViewController. If the
// device can not send email messages,
// [[MFMailComposeViewController alloc] init] will return nil. Your app
// will crash when it calls -presentViewController:animated:completion: with
// a nil view controller.
if ([MFMailComposeViewController canSendMail])
// The device can send email.
{
[self displayMailComposerSheet];
}
else
// The device can not send email.
{
self.feedbackMsg.hidden = NO;
self.feedbackMsg.text = #"Device not configured to send mail.";
}
}
- (IBAction)showSMSPicker:(id)sender
{
// You must check that the current device can send SMS messages before you
// attempt to create an instance of MFMessageComposeViewController. If the
// device can not send SMS messages,
// [[MFMessageComposeViewController alloc] init] will return nil. Your app
// will crash when it calls -presentViewController:animated:completion: with
// a nil view controller.
if ([MFMessageComposeViewController canSendText])
// The device can send email.
{
[self displaySMSComposerSheet];
}
else
// The device can not send SMS.
{
self.feedbackMsg.hidden = NO;
self.feedbackMsg.text = #"Device not configured to send SMS.";
}
}
- (void)displayMailComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Support for Brick Smasher Extreme"];
// Set up recipients
NSArray *toRecipients = [NSArray arrayWithObject:#"help.bricksx#gmail.com"];
//NSArray *ccRecipients = [NSArray arrayWithObjects:#"second#example.com", #"third#example.com", nil];
//NSArray *bccRecipients = [NSArray arrayWithObject:#"fourth#example.com"];
[picker setToRecipients:toRecipients];
//[picker setCcRecipients:ccRecipients];
//[picker setBccRecipients:bccRecipients];
// Attach an image to the email
//NSString *path = [[NSBundle mainBundle] pathForResource:#"rainy" ofType:#"jpg"];
//NSData *myData = [NSData dataWithContentsOfFile:path];
//[picker addAttachmentData:myData mimeType:#"image/jpeg" fileName:#"rainy"];
// Fill out the email body text
NSString *emailBody = #"Message:";
[picker setMessageBody:emailBody isHTML:YES];
//[self presentViewController:picker animated:YES completion:NULL];
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:picker
animated:YES
completion:nil];
}
- (void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
self.feedbackMsg.hidden = NO;
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
self.feedbackMsg.text = #"Result: Mail sending canceled";
break;
case MFMailComposeResultSaved:
self.feedbackMsg.text = #"Result: Mail saved";
break;
case MFMailComposeResultSent:
self.feedbackMsg.text = #"Result: Mail sent";
break;
case MFMailComposeResultFailed:
self.feedbackMsg.text = #"Result: Mail sending failed";
break;
default:
self.feedbackMsg.text = #"Result: Mail not sent";
break;
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
#end
The error is: Warning: Attempt to present <MFMailComposeViewController: 0xbf95170> on <UIViewController: 0xbf78d10> whose view is not in the window hierarchy!
I'm trying to send email through my app. Using MFMailComposeViewController, it always gives an error (above). But when I use the SMS part, there is no problem at all.
Using: Xcode 5, iOS 7, iPhone Retina 4"
Your problem is likely here:
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:
First of all, you're already calling this from a ViewController, so you can just [self presentViewController:]. It does sound like maybe you're calling your displayMailComposerSheet before ViewController's view is visible (viewDidLoad or viewWillAppear maybe), which would raise the error you're seeing.
use
[self presentViewController:picker animated:YES completion:nil];
instead of
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:picker animated:YES completion:nil];

MFMailComposeViewController : cancel doesn't exit to my app?

I'm trying to send a mail with MFMailComposeViewController. It happens when I click a button on my app. Of course when I click the Cancel button of the mail controller I want to go back to my app view but it doesn't work. What to do ? Here is my code :
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:#"Subject"];
[controller setMessageBody:#"<html>Test</html>" isHTML:YES];
[controller setToRecipients:nil];
if(controller) [self presentModalViewController:controller animated:YES];
Thanks for your advices
Have you implemented this delegate method? It's called after the composer is exited by the user.
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error
{
[self dismissViewControllerAnimated:YES completion:nil];
return;
}

Objective C: Send email without leaving app

How do I send an email within an app without leaving the app.
This works:
-(void) sendEmailTo:(NSString *)to withSubject:(NSString *)subject withBody:(NSString *)body {
NSString *mailString = [NSString stringWithFormat:#"mailto:?to=%#&subject=%#&body=%#",
[to stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
[subject stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
[body stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:mailString]];
}
but goes to the mail app to send. Is there a way to do this without leaving the app?
Yes. Use the MFMailComposeViewController.
// From within your active view controller
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailCont = [[MFMailComposeViewController alloc] init];
mailCont.mailComposeDelegate = self;
[mailCont setSubject:#"yo!"];
[mailCont setToRecipients:[NSArray arrayWithObject:#"joel#stackoverflow.com"]];
[mailCont setMessageBody:#"Don't ever want to give you up" isHTML:NO];
[self presentViewController:mailCont animated:YES completion:nil];
}
// Then implement the delegate method
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self dismissViewControllerAnimated:YES completion:nil];
}
Add MessageUI framework:
Click on the project
Select "Build Phases"
Expand "Link Binary With Libraries"
Click "+" and type "Message" to find "MessageUI" framework, then add.
In current view controller add import and implement a protocol:
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
#interface MyViewController : UIViewController<MFMailComposeViewControllerDelegate>
Add methods:
-(void)sendEmail {
// From within your active view controller
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailCont = [[MFMailComposeViewController alloc] init];
mailCont.mailComposeDelegate = self; // Required to invoke mailComposeController when send
[mailCont setSubject:#"Email subject"];
[mailCont setToRecipients:[NSArray arrayWithObject:#"myFriends#email.com"]];
[mailCont setMessageBody:#"Email message" isHTML:NO];
[self presentViewController:mailCont animated:YES completion:nil];
}
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[controller dismissViewControllerAnimated:YES completion:nil];
}
Updated for iOS 6. Please note that this uses ARC and does not use the deprecated modal view presentation:
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
#interface MyViewController : UIViewController<MFMailComposeViewControllerDelegate>
And then the code to present the email screen:
- (IBAction)emailButtonPushed:(id)sender {
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailCont = [[MFMailComposeViewController alloc] init];
mailCont.mailComposeDelegate = self;
[mailCont setSubject:#"Your email"];
[mailCont setMessageBody:[#"Your body for this message is " stringByAppendingString:#" this is awesome"] isHTML:NO];
[self presentViewController:mailCont animated:YES completion:nil];
}
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
//handle any error
[controller dismissViewControllerAnimated:YES completion:nil];
}