是的!我做到了!我不敢相信,但我解决了问题!这与:
将 MFMailComposeViewController 作为模态从其他一些打开的模态控制器中打开(及以上)
不幸的是,我不得不再次承认,在 iPhone 5 价格不菲的时代,Apple 仍然强迫开发人员使用陈旧、有缺陷且不方便的代码和组件! MFMailComposeViewController 就是一个很好的例子。
但是现在让我们继续更愉快的事情。
我们有什么:
- 此问题出现在装有 iOS 5.1 的 iPhone 和装有 iOS 6 的模拟器上。
- 核心问题是当您尝试将电子邮件控制器作为另一个模态控制器的模态控制器打开时。
- [MFMailComposeViewController canSendMail] 对我来说完全没有效果 - 它在这两种情况下都不起作用(无论有没有可用的电子邮件功能,它都会崩溃)。
- [self dismissModalViewControllerAnimated:NO/YES] 没有改变一般的感觉 - 它在两个方面都崩溃了,但行为略有不同。
- 我试图对 mailComposeDelegate 使用标准方法(例如 '.mailComposeDelegate = self')。
- 我从以下两者调用电子邮件发送控制器:通用(第一级)控制器以及同一个应用程序中的模态(第二级)控制器。
- 应用程序并非总是崩溃 - 有时控制器无法自行关闭(“取消”和“发送”按钮处于活动状态,但未处理任何操作)。取决于条件(谁是打开控制器的父级,是动画还是没有出现等)。
- 添加或不添加任何电子邮件收件人也没有区别。
所以,我杀死的 5 个工作小时发现的是,代表似乎在某个时候“释放”了。我可以假设,如果您将电子邮件控制器作为模态打开而不是其他模态控制器,那么(以前的模态)控制器正在被垃圾收集器或其他方式清理,并且委托也被清理(我不希望花费更多时间进行详细挖掘,所以我将把它留给 Apple 的良心)。
不管怎样,用两个词来说,我的解决方案是
用“强”引用将委托对象保存在某处。
在我的情况下,该委托的所有者是主视图控制器类(在我的情况下始终可用,因为大多数应用程序逻辑都在使用它)。也可以是 AppDelegate 实例。
看起来像:
@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
坦率地说,代码有点乱,但这只是一般的想法。
我希望,你会更好地管理自己的。
祝你好运,上帝保佑微软! ^^