It's one of the simplest things to do, I know. But I've been banging my head against this for days. I've done it plenty of times in the past, but for some reason trying to present a modal view controller just crashes the app to a black screen. Nothing reported in the console or anything. I'm hoping someone might have had this problem and has some advice.
This code is called from a UIViewController class:
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];
Yes! I did it! I can not believe, but I solved the problem! That's related to:
Opening an MFMailComposeViewController as modal from (and over) some other opened modal controller
Unfortunately, I have to admit that, again, in times of expensive-like-a-Devil-iPhones5, Apple still forses developers to use old, buggy and not convenient code and components! The great example of that is MFMailComposeViewController.
But now let's follow to more pleasant things.
What do we have:
So, what my killed 5 working hours discovered is that seems the delegate is "releases" somehow somewhen. I can suppose that if you are opening the email controller as modal over some other modal controller, that (previously modal) controller is being cleaned by garbage collector or some other way and that way the delegate is being cleaned as well (I have no wish to kill several more hours for detailed digging, so I'd leave that to Apple's conscience).
Anyway, in two words, my solution was
to hold the delegate object somewhere with "strong" reference.
in my case, the owner of that delegate was main view controller class (which is always available in my case, as most of the app logic is working with it). That can be AppDelegate instance also.
It would look like:
Frankly saying, the code is kind of messy, but this is just general thoughts. I hope, you'll manage your own much nicer.
Good luck and God bless Microsoft! ^^
As Andrew has pointed out in his comment, do you check
before trying to push the view controller? The behavior of the
MFMailComposeViewController
is not well defined if this method returns NO (which may also well be the case when running on the simulator, though I'm not sure). From the documentation:Have you tried to push another view controller instead? Does this crash your app, too?
Are you showing another modal view controller before trying to show MFMailComposeViewController? I had the same problem and found a workaround:
I know it's an ugly workaround, but I didn't found anything better :(
I don't know how relevant this is, but I have been having horrible problems trying to present the MFMailComposeViewController after returning to my main view controller from ANOTHER modal view controller. It just would not work. I was trying to dismiss this other modal view controller before launching the mail controller, and found my solution to be to not call:
But to instead call:
Then go ahead and present the mail view controller.
That one change made all the difference in my case. I suspect this is connected to the problem sgosha was having. Just switch off the animation, rather than putting a delay in (which is probably just waiting until the animation has completed). Looks like a bug in the framework to me.
I should probably explain further. I have a share button on my main view controller, which modally pops up a table view to allow to user to choose what they want to share. From here, if they tap on Email, they get a UIActionSheet letting them further decide which files they wish to attach to their email.
It is possible the UIActionSheet in the mix is contributing to the problem. The actual dismissal of the modal view controllers is taking place in the delegate methods back in my main view controller, and it is this main view controller which tries to launch the mail view controller after dismissing the modal table view controller.