Dismissing a MFMailComposeViewController causes EXC_BAD_ACCESS

若如初见. 提交于 2019-12-05 11:50:36

I found the problem.

We're using a library called ShareKit to do some Twitter and Facebook integration. Since we already had our own email form, we didn't need ShareKit to handle it for us, so we deleted the ShareKit's email handling files.

All was well, except that in its initialization, ShareKit does this:

SHKSwizzle([MFMailComposeViewController class], @selector(viewDidDisappear:), @selector(SHKviewDidDisappear:)); 

Where SHKSwizzle basically replaces MFMailComposerViewController's viewDidDisappear: method with SHKviewDidDisappear: (Don't ask me why... I think that's horrible).

Anyway, it turns out that SHKviewDidDisappear was in ShareKit's mail handler, so deleting the file how makes the code jump to hyperspace and crash horribly. Restoring the file again fixes the problem.

Ugh.

Thanks everyone for your help!

Just a hunch, but what looks odd to me are these lines:

[[self parentViewController] presentModalViewController:controller animated:YES];

and

[[self parentViewController] dismissModalViewControllerAnimated: YES];

True, I don't know about your arrangement of view controllers, but isn't it a little unusual to reference [self parentViewController] directly? You're heavily coupling three view controllers (the caller, the parent, and the modal view); this discourages code/view controller reusability (e.g. if you wanted to reuse the same view controller inside a different view hierarchy elsewhere in the app).

The only reason I can imagine you may want to do this is that the parent is a UINavigationController/UITabBarController, and since that is the top view, you want that view controller to be presenting the modal.

In this case I use:

[[self navigationController] presentModalViewController:controller animated:YES]

Or better yet, in a Tab Bar situation, I have my root view controller register an observer listening for notifications, and then all modals are launched from the root view controller.

Could I get a little more detail about your view stack? Also, could you try once just calling on "self" instead of the parent and see what happens?

It's probably getting autoreleased out from under you. I've seen this happen with a UIDocumentInteractionController as well. The best solution is probably to retain the MFMailComposeViewController in an instance variable and then release it in didFinishWithResult.

If you want to dismiss the mail composer, the best way to do is like this

- (void) mailComposeController: (MFMailComposeViewController *) controller didFinishWithResult: (MFMailComposeResult) result error: (NSError *) error 
{
  [controller dismissModalViewControllerAnimated: YES];
}

That way you need not worry much about the controller or its parent or anything

And also for presenting the composer, Instead of using

 [[self parentViewController] presentModalViewController:controller animated:YES];

try using

 [self presentModalViewController:controller animated:YES];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!