5

某处:

if([MFMailComposeViewController canSendMail])
{
    MFMailComposeViewController *email_vc = [[MFMailComposeViewController alloc] init];
    email_vc.mailComposeDelegate = self;

    [email_vc setSubject:subject];
    [email_vc setMessageBody:message isHTML:FALSE];
    [email_vc setToRecipients:recipients];

    [self presentModalViewController:email_vc animated:FALSE];
    [[UIApplication sharedApplication] setStatusBarHidden:TRUE];
    [email_vc release];
}
else
...

别的地方:

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    switch (result) 
    {
        case MFMailComposeResultCancelled:
            NSLog(@"Cancelled");
            break;

        case MFMailComposeResultSaved:
            NSLog(@"Saved");
            break;

        case MFMailComposeResultSent:
            NSLog(@"Sent");
            break;

        case MFMailComposeResultFailed:
            NSLog(@"Compose result failed");
            break;

        default:
            NSLog(@"Default: Cancelled");
            break;
    }

    // This ugly thing is required because dismissModalViewControllerAnimated causes a crash
    // if called right away when "Cancel" is touched.

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_current_queue(), ^
    {
        [self dismissModalViewControllerAnimated:FALSE];
    }); 

}

那个丑陋的“dispatch_after”块是我可以让它在不崩溃的情况下工作的唯一方法。

上下文是在电子邮件撰写视图控制器上触摸“发送”以外的任何内容都会导致崩溃。有没有办法解决这个问题而不必求助于这个丑陋的创可贴?我关于创可贴的理论是,当您触摸“取消”以确认用户确实想要取消时,会呈现一个中间视图。我想知道是否[self dismissModalViewControllerAnimated:FALSE];试图消除一个不合顺序的视图或类似的东西。通过插入一个小的延迟,我推测邮件撰写视图在被要求离开之前有时间进行清理。

我在另一个问题中看到了延迟。但作者并没有详细说明:

iPad 的 MFMailComposeViewController 崩溃

编辑 1:添加崩溃日志

Incident Identifier: ****************
CrashReporter Key:   *****************
Hardware Model:      iPhone4,1
Process:         ************* [9038]
Path:            /var/mobile/Applications/*********************
Identifier:      ***********************
Version:         ??? (???)
Code Type:       ARM (Native)
Parent Process:  launchd [1]

Date/Time:       2012-07-20 11:25:53.704 -0700
OS Version:      iPhone OS 5.0.1 (9A405)
Report Version:  104

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0xa003853a
Crashed Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x316b9fbc 0x316b6000 + 16316
1   UIKit                           0x350caa9e 0x34f8e000 + 1297054
2   UIKit                           0x34fa6814 0x34f8e000 + 100372
3   UIKit                           0x34fabfb2 0x34f8e000 + 122802
4   QuartzCore                      0x33354ba0 0x33329000 + 179104
5   libdispatch.dylib               0x37896f74 0x37894000 + 12148
6   CoreFoundation                  0x37bac2d6 0x37b20000 + 574166
7   CoreFoundation                  0x37b2f4d6 0x37b20000 + 62678
8   CoreFoundation                  0x37b2f39e 0x37b20000 + 62366
9   GraphicsServices                0x376adfc6 0x376aa000 + 16326
10  UIKit                           0x34fbf73c 0x34f8e000 + 202556
11  *****************               0x00002346 main (main.m:14)
12  *****************               0x00002304 start + 32

编辑 2:经过多次挠头,这似乎是一个真正的 Apple 错误。

我下载并运行了 MailComposer 示例项目:

http://developer.apple.com/library/ios/#samplecode/MailComposer/Introduction/Intro.html

它工作正常。

然后我编辑了代码以在显示和关闭邮件撰写控制器时删除动画。

[self presentModalViewController:picker animated:FALSE];

[self dismissModalViewControllerAnimated:FALSE];

果然,当使用“取消”关闭电子邮件撰写 UI 时,它崩溃了。

运行僵尸带来了这一点:

-[MFMailComposeController actionSheet:didDismissWithButtonIndex:]: message sent to deallocated instance 0x7479ef0

我猜操作表会收到关闭消息,而不是邮件撰写视图控制器。

如果有人可以确认行为,我会报告错误。

编辑 3:报告了错误。

我接受的答案很好地解释了导致此问题的潜在机制。此外,在回答评论的来回过程中,还确定了两个额外的解决方法。所有创可贴,但现在有几个选择。

我还没有检查过,但我怀疑 ShareKit 也受到这个错误的影响(如果邮件撰写视图控制器的演示没有动画)。

4

2 回答 2

6

我猜操作表会收到关闭消息,而不是邮件撰写视图控制器。

不完全的。

事件的顺序可能是这样发生的:

  • 操作表调用-actionSheet:clickedButtonAtIndex:其委托(MFMCVC)。
    • MFMailComposeViewController 调用-mailComposeController:didFinishWithResult:error:它的委托(你的 VC)
      • 你的 VC 电话[self dismissModalViewControllerAnimated:NO]
        • 这会导致 MFMCVC 被释放。由于解雇没有动画,因此不再有任何涉及 MFMCVC 的内容。它被释放了!
  • 行动表调用-actionSheet:didDismissWithButtonIndex:其代表
    • 但是它的代表已经被释放了!
      • 所以它崩溃了!

解决方法是让 AppleactionSheet.delegate = nil-dealloc.

一个潜在的解决方法

[[self.modalViewController retain] autorelease]
[self dismissModalViewControllerAnimated:NO]

如果您使用 ARC,这会有点棘手。

于 2012-07-21T01:02:22.577 回答
2

这对我有用:

- (void) mailComposeController: (MFMailComposeViewController *) controller
       didFinishWithResult: (MFMailComposeResult) result
                     error: (NSError *) error {

if(result == MFMailComposeResultSent){
    [self dismissViewControllerAnimated:YES completion:NULL];
} else if (result == MFMailComposeResultCancelled) {
    [self dismissViewControllerAnimated:YES completion:NULL];
}

}

于 2012-09-10T14:51:55.943 回答