【问题标题】:presentModalViewController crashes my apppresentModalViewController 使我的应用程序崩溃
【发布时间】:2010-11-08 03:37:53
【问题描述】:

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

这段代码是从 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];

【问题讨论】:

  • 您是否正在检查以确保设备已设置邮件?顺便说一句,我也认为你正在泄漏控制器:在那里添加一个自动释放。
  • 是的,我正在检查邮件功能并释放控制器,我只是没有包含这些代码行。是 presentModalViewController 导致了这个问题。我试过展示其他视图控制器,但它仍然崩溃。
  • 嗯.. 已经晚了几秒钟.. 我想你可以放心地忽略我的回答。 ;-) 祝你好运!
  • 模拟器是否表现出相同的行为?您是否尝试过注释掉委托分配?
  • 好的,所以如果不是邮件撰写 VC,我想有关此代码上下文的更多信息会很好。到目前为止,您提供的 sn-p 看起来还不错。

标签: iphone uiviewcontroller modal-dialog mfmailcomposeviewcontroller


【解决方案1】:

是的!我做到了!我不敢相信,但我解决了问题!这与:

将 MFMailComposeViewController 作为模态从其他一些打开的模态控制器中打开(及以上)

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


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

我们有什么:

  • 此问题出现在装有 iOS 5.1 的 iPhone 和装有 iOS 6 的模拟器上。
  • 核心问题是当您尝试将电子邮件控制器作为另一个模态控制器的模态控制器打开时
  • [MFMailComposeViewController canSendMail] 对我来说完全没有效果 - 它在这两种情况下都不起作用(无论有没有可用的电子邮件功能,它都会崩溃)。
  • [self dismissModalViewControllerAnimated:NO/YES] 没有改变一般的感觉 - 它在两个方面都崩溃了,但行为略有不同。
  • 我试图对 ma​​ilComposeDelegate 使用标准方法(例如 '.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

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

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

【讨论】:

    【解决方案2】:

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

    [self dismissModalViewControllerAnimated:YES];
    

    但改为调用:

    [self dismissModalViewControllerAnimated:NO];
    

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

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

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

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

    【讨论】:

      【解决方案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];
        } 
      }
      

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

      【讨论】:

        【解决方案4】:

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

        +[MFMailComposeViewController canSendMail]
        

        在尝试推送视图控制器之前?如果此方法返回 NO,MFMailComposeViewController 的行为未明确定义(在模拟器上运行时也可能出现这种情况,但我不确定)。来自文档:

        在使用这个类之前,你必须 总是检查当前是否 设备配置为发送电子邮件至 全部使用 canSendMail 方法。如果 用户的设备未设置为 发送电子邮件,您可以通知 用户或只是禁用电子邮件 在您的应用程序中调度功能。 你不应该尝试使用这个 接口 if canSendMail 方法 返回号码。

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

        【讨论】:

        • 看看这个: UIViewController *tester = [[UIViewController alloc] initWithNibName:@"TestNib" bundle:nil]; [self presentModalViewController:tester animated:YES];它崩溃了!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-26
        • 2013-08-20
        • 2021-08-28
        • 2012-05-09
        • 2014-01-24
        • 1970-01-01
        • 2015-12-21
        相关资源
        最近更新 更多