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: バグが報告されました。

私が受け入れた回答には、この問題を引き起こしている潜在的なメカニズムがよく説明されています。また、回答コメントのやり取り中に、2 つの追加の回避策が特定されました。すべてのバンドエイドですが、現在はいくつかの選択肢があります.

まだ確認していませんが、ShareKit もこのバグの影響を受けていると思われます (メール作成ビュー コントローラーの表示がアニメーション化されていない場合)。

4

2 に答える 2

6

アクションシートは、メール作成ビューコントローラーの代わりに却下メッセージを受け取ると思います。

そうではありません。

イベントのシーケンスは、おそらく次のように発生します。

  • アクション シートは-actionSheet:clickedButtonAtIndex:、デリゲート (MFMCVC) を呼び出します。
    • MFMailComposeViewController は-mailComposeController:didFinishWithResult:error:、デリゲート (VC) で呼び出します
      • あなたの VC コール[self dismissModalViewControllerAnimated:NO]
        • これにより、MFMCVC が解放されます。却下はアニメーション化されていないため、MFMCVC を参照するものは何もありません。解放されます!
  • -actionSheet:didDismissWithButtonIndex:デリゲートでの アクション シート呼び出し
    • しかし、そのデリゲートは割り当て解除されました!
      • だからクラッシュ!

修正は、Apple が で行うことactionSheet.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 に答える