iphone - adding the view of MFMailComposeViewController (in-app email) - iphone

I've spent the past two days just trying to enable the sending of email from within my app. Hoping one of the smart folks on here can help me out.
presentModalViewController doesn't work for me (just crashes the app with no explanation as to why), so I'm forced to add the view of MFMailComposeViewController. Here's my attempt:
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:#"test subject"];
[controller setMessageBody:#"this is the message body" isHTML:NO];
// [self presentModalViewController:controller animated:YES]; //this crashes the app
//so I try this instead:
controller.view.frame = CGRectMake(0,0,480,320);
[self.view addSubview:controller.view];
[controller release];
What gets added to the screen is the subject bar only, with cancel and send buttons. None of the text fields (To:, Cc:, Subject, body) are displayed. Why aren't they a part of MFMailComposeViewController's view, and how can I display them?

Honestly, you should be using presentModalViewController. Rather than force your way around the SDK, consider debugging the crash. Turn on the debugger and see if there are any exceptions logged in the console. Check for crash logs, etc...
Also, make sure that self is a proper delegate and a UIViewController subclass.

I 've solved this problem:
try NOT this:
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
but THIS:
MFMailComposeViewController *mailComposeViewController = [MFMailComposeViewController new];

You should instead try:
[[self navigationController] presentModalViewController...];
Since that's the proper way to present it. Trying to add its view manually is unfortunately utterly incorrect and will never work.

Well I have determined that one must create a dummy view controller otherwise the darn thing won't slide in.
I create a class called Sys_Mail that is a #interface Sys_Mail : UIViewController <MFMailComposeViewControllerDelegate>
and then i create basically a root view view controller. I wrestled with portrait/landscape for hours but determined that if you attach the view controller to the top level view (which contains my landscape transform) then it slides in as a landscape window. There is just one visual glitch, the parent window gets moved around for a few seconds while the new window slides in, this is a side effect of the landscape transform doing odd things to the parent....
in order to get landscape orientation on the sliding window you must declare a method in your Sys_Mail class that handles the autorotate message:
//=======================
// shouldAutorotateToInterfaceOrientation
//=======================
// see if this ever gets called for the view controller
-(BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation
{
if (TRACE) printf ("shouldAutorotateToInterfaceOrientation\n");
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight); // or whatever orientation is needed
}
the variable gMasterView refers to my top level view (that has the landscape transform and is attached to the window). Subviews don't seem to work, view controllers are awful THEY ARE MORE DESIGN PATTERN CRAP. I want total control of my views not some microsoft MFC type crud!
Sys_Mail* g_root_vc;
if (g_root_vc == nil) {
// create an empty view controller so we have something to work with
g_root_vc = [[Sys_Mail alloc] init];
g_root_vc.view = (UIView*) gMasterView;
}
so this

I have the same crash and finally I can fix it by sending presentModalViewController message to [self navigationController].
Here is my code:
// Create the Mail composer view controller
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
// Set the view controller delegate
controller.mailComposeDelegate = self;
// Set recipients, if you want
[controller setToRecipients:recipients];
// Set subject, if you want
[controller setSubject:#"The subject"];
// Set message body, if you want
[controller setMessageBody:#"The message body" isHTML:YES]; // isHTML -> YES/NO depending the message body
// Present the view controller
[[self navigationController] presentModalViewController:controller animated:YES];
// Memory management
[controller release];
I hope this can help!

Related

instance method presentModalViewController:animated not found

I am implementing email composer in app delegate.
I am not sure why , but i am getting an warning
"instance method presentModalViewController:animated not found"
only at the appdelegate,whereas, i am using the the same method in my other viewcontroller, which works smoothly.
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
if([MFMailComposeViewController canSendMail])
{
//Setting up the Subject, recipients, and message body.
[mail setToRecipients:[NSArray arrayWithObjects:#"abc#gmail.com",nil]];
UIImage *pic = [UIImage imageNamed:#"page0.png"];
NSData *exportData = UIImageJPEGRepresentation(pic ,1.0);
[mail addAttachmentData:exportData mimeType:#"image/jpeg" fileName:#"Picture.jpeg"];
[mail setSubject:#"dummy text"];
[mail setMessageBody:#"Please tell us what your concerns are and we will try to fix them" isHTML:NO];
//Present the mail view controller
[self presentModalViewController:mail animated:YES];
//release the mail [mail release];
}
[self presentModalViewController:mailer animated:YES]; this is giving warning and app gets crashed,when reach here.
Any suggestions.
[self presentModalViewController:mail animated:YES];
is UIViewControllers Method . Please check whether you have extended your class from UIViewController
#interface abc : UIViewController
#NiravPatel: Thanks. You gave me the clue. But i had to replace "mail" by "mailer" in my case.
So, I got it work under iOS7 with
[self presentViewController:mailer animated:YES completion:nil];
presentModalViewController is a method for UIViewController's subclass and not for appDelegate, since it do not have any view controller of itself.
What you can do is, present it to last view controller of navigation controller if you are using that
Why implement this in your app delegate. I would just make a separate view and put whatever your AppDelegate is doing on the view and then implement this code in the viewcontroller. Trying to implement code like PresentModalViewController is not possible in a AppDelegate. Just create a new view and point the app delegate to load that view on startup.
presentModalViewController:animated: won't work because that's method of UIViewController but self here is an app delegate.
Refer View Controllers link for more reference
it is because that presentModalViewController is deprecated in ios 6.so for ios 6 you have to write the method like below
[self presentViewController:mail animated:YES completion:nil];
let me know it is working or not...!!!!
Happy Coding!!!!!!

MFMailComposeViewController is not interactive

I'm using the following code in two view controllers; one, where it is triggered by pressing a button, and another, where it is triggered by tapping a table cell. In the first, it works fine.
In the second, triggered by the table-cell tap, the mail composer appears, with the fields correctly filled out, but the cursor and keyboard do not appear, so you can't actually enter anything into the mail message. (You can hit Cancel or Send without problems.) Any idea what's wrong? Thanks!
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Message subject"];
[picker setMessageBody:#"Sample message" isHTML:NO];
[self presentModalViewController:picker animated:YES];
[picker release];
} else {
NSLog(#"cant send mail");
}
I figured out the problem, but it's absolutely ridiculous -- probably a bug in the SDK. I was presenting the problem UIViewController with a UIModalTransitionStyleFlipHorizontal, while I was presenting the healthy UIViewController with the default transition style. Something about the UIModalTransitionStyleFlipHorizontal seems to make the presented view controller greedy to be first-responder; it won't give up first-responder status to the launched MFMailComposeViewController.

Blank MFMailComposeViewController the second time it is presented?

I got a strange problem with MFMailComposeViewController.
The first time it is displayed using presentModalViewController:animated, everything works perfectly.
The second time it is blank, with nothing on screen except for the navigation bar, the Cancel & Send button.
I have already set the mailComposeDelegate correctly, and dismiss the view controller properly in the delegate.
Any idea why that happens?
EDIT: The code is:
- (void)viewDidLoad {
mailComposeViewController = [[MFMailComposeViewController alloc] init];
[mailComposeViewController setMailComposeDelegate:self];
}
- (void)dealloc {
[mailComposeViewController release];
}
- (void)mail {
[self presentModalViewController:mailComposeViewController animated:YES];
}
Okay, I somehow solved my problem. I moved my MFMailComposeViewController's init & release code from viewDidLoad & dealloc, respectively to exactly where I choose to present the view controller.
Then, it worked.

iPhone MailComposer class UIViewController dismissModalViewControllerAnimated issues

I created a class to launch the MailComposer so that my iPhone app would only have one place to go when generating various kinds of e-mail: some with attachments, some not. Some with pre-filled addresses, some not.
I didn't want my class implement UIViewController, but it has to so it can be the delegate for the MailComposer. Otherwise, the view controllers that call my class would themselves have to be delegates for the MailComposer, which defeats the purpose.
The downside of having my class be a view controller is that it has to load to the screen before it can modally bring up the MailComposer. Unfortunately, view controllers can't be transparent. The effect is, whatever is on screen gets covered by a solid white view controller for a moment before the MailComposer appears.
I could maybe live with that, but not this: after the MailComposer goes away, I'm left with my blank view controller occupying the screen. I ought to be able to get rid of it from within itself by calling this:
[self.parentViewController dismissModalViewControllerAnimated:NO];
But that dies a horrible death: "Loading 43365 stack frames..."
Has my class -- a UIViewController that pre-fills and then launches a MailComposer -- lost track of its parentViewController? It isn't nil, because I've tested for that.
As launched from within the current view controller...
// My class is called Email.
Email *oEmail = [[[Email alloc] init] retain];
// Red, to remind myself that I'd like to someday learn to make it transparent.
oEmail.view.backgroundColor = [UIColor redColor];
// Pre-fill whatever fields you want, and specify attachments.
oEmail.EmailSubject = #"I am truly stumped";
// This has to go on screen first.
[self presentModalViewController:oEmail animated:NO];
// Then this can happen, which brings up the MailComposer.
[oEmail f_SendEmail];
// Commenting out the next line didn't help, so I turned it back on.
[oEmail release];
Inside the class, you need the mailComposeController:didFinishWithResult:error: method to make the MailComposer go away, and for that to happen, the class has to be the MFMailComposeViewControllerDelegate. Here's what happens in there:
// This gets rid of the mail composer.
[self dismissModalViewControllerAnimated:YES];
// This never fails to get rid of other modal view controllers when called
// from within those controllers, but boy does it not work here.
[self.parentViewController dismissModalViewControllerAnimated:NO];
If you can help me, I will be truly thankful!
Instead of calling
[self.parentViewController dismissModalViewControllerAnimated:NO];
I would set up a delegate for your 'Email' controller.
An example of this sort of connection can be seen in the 'FlipSide' application template when creating a new project.
Basically, you would set up a delegate for the Email controller:
Email *oEmail = [[[Email alloc] init] retain];
oEmail.view.backgroundColor = [UIColor redColor];
oEmail.EmailSubject = #"I am truly stumped";
[self presentModalViewController:oEmail animated:NO];
[oEmail f_SendEmail];
[oEmail setDelegate:self];
[oEmail release];
Then in the Email .h file:
#protocol EmailDelegate
-(void)emailDidFinish;
#end
#implementation Email : UIViewController {
// Other stuff
id <EmailDelegate> delegate;
}
#property (nonatomic, assign) id <EmailDelegate> delegate;
#end
Make sure you #synthesize delegate, then when you're ready to dismiss it call:
// This gets rid of the mail composer.
[self dismissModalViewControllerAnimated:YES];
// This never fails to get rid of other modal view controllers when called
// from within those controllers, but boy does it not work here.
if (delegate && [delegate respondsToSelector:#selector(emailDidFinish)]){
[delegate emailDidFinish];
}
And finally, in your original view controller, make sure you've got in the .h file and then have:
-(void)emailDidFinish {
[self dismissModal...];
}
Hope that helps.
I had the same problem and I solved it a different way.
I created a function which pops current ViewController.
In the h:
-(void)ics;
In the cpp:
-(void)ics{
//[self.navigationController popViewControllerAnimated:NO];
[self.navigationController popToRootViewControllerAnimated:YES];
}
and called it after dismissing the MailComposer:
[self dismissModalViewControllerAnimated:YES];
[self ics];
voila!

MFMailComposeViewController displaying only bar

MFMailComposeViewController displaying only bar at the top of the screen with the cancel and send buttons. Code for landscape:
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:#"In app email..."];
[controller setMessageBody:#"...Hi, all...." isHTML:NO];
//[self presentModalViewController:controller animated:YES];
controller.view.frame = CGRectMake(0,0,480,320);
[self.view addSubview:controller.view];
[controller release];
What is problem?
i've ever seen this problem before, as far as i know, you shouldn't replace the presentModalViewController method with addsubview.
I was getting this behavior, as well as the modal view coming in from the side and the modal view was stopping a quarter of the way through presenting.
In my app I had many view controllers stacked with addSubview:. I don't know why but it worked to present the modal view from the bottom view controller. I did something like this:
[((FirstViewController*)[UIApplication sharedApplication].delegate).firstViewControllerInstance sendEmailwithInfo];
Hope that helps! And maybe someone can give some insite as to why it was happening.