2

我知道,这是最简单的事情之一。但是我这几天一直在反对这个。过去我已经做过很多次了,但由于某种原因,试图呈现模态视图控制器只会使应用程序崩溃到黑屏。控制台中没有任何报告或任何内容。我希望有人可能遇到过这个问题并有一些建议。

此代码是从 UIViewController 类调用的:

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];
4

4 回答 4

3

正如安德鲁在他的评论中指出的那样,你检查

+[MFMailComposeViewController canSendMail]

在尝试推动视图控制器之前?MFMailComposeViewController如果此方法返回 NO(在模拟器上运行时也可能是这种情况,但我不确定),则的行为没有明确定义。从文档中:

在使用此类之前,您必须始终检查当前设备是否配置为使用 canSendMail 方法发送电子邮件。如果用户的设备未设置用于发送电子邮件,您可以通知用户或简单地禁用应用程序中的电子邮件发送功能。如果 canSendMail 方法返回 NO,则不应尝试使用此接口。

您是否尝试过推送另一个视图控制器?这也会使您的应用程序崩溃吗?

于 2009-07-04T22:59:53.143 回答
3

您是否在尝试显示 MFMailComposeViewController 之前显示另一个模态视图控制器?我遇到了同样的问题并找到了解决方法:

- (void)peopleMultiPickerNavigationController:(PeopleMultiPickerNavigationController *)peoplePicker 
                                didSelectContacts:(NSArray *)contacts {

[self dismissModalViewControllerAnimated:YES];

// some more code here

[self performSelector:@selector(sendEmail) withObject:nil afterDelay:0.45]; // this works only if delay > ~0.4!
// [self sendEmail]; // this won't work

// some more code here

}

- (void) sendEmail {
  Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));
  if (mailClass != nil) {
    // We must always check whether the current device is configured for sending emails
    if ([mailClass canSendMail]) {
      [self displayComposerSheet:emails];
    } else {
      [self launchMailAppOnDevice:emails];
    }
  } else {
    [self launchMailAppOnDevice:emails];
  } 
}

我知道这是一个丑陋的解决方法,但我没有找到更好的方法:(

于 2009-07-12T15:23:27.493 回答
2

我不知道这有多相关,但是在从另一个模态视图控制器返回到我的主视图控制器后,我在尝试呈现 MFMailComposeViewController 时遇到了可怕的问题。它只是行不通。在启动邮件控制器之前,我试图关闭这个其他模式视图控制器,并发现我的解决方案是不调用:

[self dismissModalViewControllerAnimated:YES];

但改为调用:

[self dismissModalViewControllerAnimated:NO];

然后继续并展示邮件视图控制器。

这一变化使我的情况完全不同。我怀疑这与 sgosha 遇到的问题有关。只需关闭动画,而不是延迟(可能只是等到动画完成)。对我来说,这看起来像是框架中的一个错误。

我可能应该进一步解释。我的主视图控制器上有一个共享按钮,它以模态方式弹出一个表格视图以允许用户选择他们想要共享的内容。从这里,如果他们点击电子邮件,他们会得到一个 UIActionSheet,让他们进一步决定他们希望将哪些文件附加到他们的电子邮件中。

混合中的 UIActionSheet 可能会导致问题。模态视图控制器的实际解除发生在我的主视图控制器中的委托方法中,正是这个主视图控制器在解除模态表视图控制器后尝试启动邮件视图控制器。

于 2012-04-08T17:05:55.223 回答
2

是的!我做到了!我不敢相信,但我解决了这个问题!这与以下内容有关:

从其他打开的模态控制器(和以上)打开一个 MFMailComposeViewController 作为模态控制器

不幸的是,我不得不再次承认,在像恶魔一样昂贵的 iPhone 5 时代,Apple 仍然强迫开发人员使用旧的、有缺陷的和不方便的代码和组件!MFMailComposeViewController 就是一个很好的例子。


但是现在让我们继续更愉快的事情。

我们有什么:

  • 这个问题出现在带有 iOS 5.1 的 iPhone 和带有 iOS 6 的模拟器上。
  • 核心问题是当您尝试从另一个模态控制器打开电子邮件控制器作为模态控制器时。
  • [MFMailComposeViewController canSendMail ]对我完全没有影响- 它在两种方式中都不起作用(它在有或没有可用的电子邮件功能时崩溃)。
  • [self dismissModalViewControllerAnimated: NO/YES ]并没有改变一般的感觉——它在两种情况下都崩溃了,但行为略有不同。
  • 我试图对mailComposeDelegate使用标准方法(如'.mailComposeDelegate = self')。
  • 我从两个调用电子邮件发送控制器:通用(第一级)控制器以及来自同一个应用程序的模态(第二级)控制器。
  • 应用程序并不总是崩溃 -有时控制器无法自行关闭(按钮“取消”和“发送”处于活动状态,但未处理任何操作)。取决于条件(谁是父母打开了控制器,是动画还是没有出现等)。
  • 是否添加了任何电子邮件收件人也没有区别。

所以,我杀死的 5 个工作小时发现的是,代表似乎在某个时候“释放”了。我可以假设,如果您将电子邮件控制器作为模态打开而不是其他模态控制器,那么(以前的模态)控制器正在被垃圾收集器或其他方式清理,并且委托也被清理(我不希望为详细挖掘再浪费几个小时,所以我会把它留给苹果的良心)。

无论如何,简而言之,我的解决方案是

将委托对象保存在具有“强”引用的某处。

就我而言,该委托的所有者是主视图控制器类(在我的情况下始终可用,因为大多数应用程序逻辑都在使用它)。那也可以是 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

坦率地说,代码有点乱,但这只是一般的想法。我希望,你会更好地管理自己的。

祝你好运,上帝保佑微软!^^

于 2012-11-27T02:16:02.847 回答