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:
- This problem appeared as on iPhone with iOS 5.1 as on Simulator with iOS 6.
- The core problem was when you are trying to open the email controller as a modal one from another modal controller.
- [MFMailComposeViewController canSendMail] had absolutely no effect for me - it did not work in both ways (it was crashing with or without email functionality available).
- [self dismissModalViewControllerAnimated:NO/YES] did not change general sense - it was crashing in both ways, but with a little different behavior.
- I was trying to use a standard approach with mailComposeDelegate (like '.mailComposeDelegate = self').
- I was calling the email sending controller from both: common (first-level) controller as well as from modal (second-level) one at the same app.
- App was not always crashing - sometimes the controller just could not dismiss itself (buttons 'cancel' and 'send' were active, but no actions processed). Dependenly on conditions (who is parent opened the controller, was animation or not on appearing etc).
- There were also no difference if any email recepients were added or not.
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:
@interface SharingTools : NSObject <MFMailComposeViewControllerDelegate>
@property UIViewController* currentParentController;
...
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
if (error)
{
...
}
else
{
// I pass it somewhere before calling the email controller dialog opener method,
// because it's different in case we open the email sender
// from first-level controller or second- (the modal one)
[currentParentController dismissViewControllerAnimated:YES completion:^{
if (_onResult) {
((void(^)(bool))_onResult)(result == MFMailComposeResultSent);
}
}];
}
// and of course clearing all the references etc here
currentParentController.mailComposeDelegate = nil;
currentParentController = nil;
}
-(void)sendEmail //... params here
// (possibly, including to store also currentParentController)
{
currentParentController = ... ;
[currentParentController presentViewController:
newlyCreatedEmailController animated:YES completion:nil];
}
@end
@interface MyMainViewController : UIViewController
@property SharingTools* sharing; // initialize somewhere (on viewDidLoad, for instance)
...
-(void)showSettings
{
...
[self presentModalViewController:settingsController animated:YES];
}
@end
@interface SettingsViewController : UIViewController
...
-(void)sendEmailSupport
{
// again, this is up to you where and how to have either reference
// to main controller (or any other owner of the delegate object)
// or sharing directly
[myMainViewControllerInstance.sharing sendEmail: ... parentController:self];
}
@end
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! ^^