2

それは最も簡単なことの1つです。しかし、私は何日もこれに頭をぶつけてきました。私は過去に何度もそれを行いましたが、何らかの理由でモーダルビューコントローラーを提示しようとすると、アプリが黒い画面にクラッシュします。コンソールなどで何も報告されません。私は誰かがこの問題を抱えていて、いくつかのアドバイスを持っているかもしれないことを望んでいます。

このコードは、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]

ビューコントローラをプッシュしようとする前に?このメソッドが NO を返す場合、 の動作はMFMailComposeViewController明確に定義されていません (よくわかりませんが、シミュレーターで実行している場合も同様です)。ドキュメントから:

このクラスを使用する前に、現在のデバイスが canSendMail メソッドを使用して電子メールを送信するように構成されているかどうかを常に確認する必要があります。ユーザーのデバイスが電子メールの配信用に設定されていない場合は、ユーザーに通知するか、アプリケーションで電子メール ディスパッチ機能を単に無効にすることができます。canSendMail メソッドが NO を返す場合は、このインターフェイスを使用しないでください。

代わりに別のView Controllerをプッシュしようとしましたか? これでアプリもクラッシュしますか?

于 2009-07-04T22:59:53.143 に答える
2

はい!やった!信じられませんが、問題は解決しました!これは以下に関連しています:

MFMailComposeViewControllerを他の開いているモーダルコントローラーから(およびそれ以上)モーダルとして開く

残念ながら、やはり、悪魔のような高価なiPhones5の時代でも、Appleは開発者に古くてバグが多く、便利ではないコードやコンポーネントを使用するように強制していることを認めなければなりません。その良い例はMFMailComposeViewControllerです。


しかし、今度はもっと楽しいことを続けましょう。

私たちは何を持っていますか:

  • この問題は、iOS6を搭載したシミュレーターと同様にiOS5.1を搭載したiPhoneでも発生しました。
  • 主要な問題は、電子メールコントローラーを別のモーダルコントローラーからモーダルコントローラーとして開こうとしたときでした。
  • [MFMailComposeViewController canSendMail ]は私にはまったく効果がありませんでした-両方の方法で機能しませんでした(利用可能な電子メール機能の有無にかかわらずクラッシュしていました)。
  • [self dismissModalViewControllerAnimated:NO / YES ]は一般的な意味を変えませんでした-両方の方法でクラッシュしていましたが、動作が少し異なりました。
  • mailComposeDelegateで標準的なアプローチを使用しようとしていました(「.mailComposeDelegate = self」など)。
  • 同じアプリの共通(第1レベル)コントローラーとモーダル(第2レベル)コントローラーの両方からメール送信コントローラーを呼び出していました。
  • アプリが常にクラッシュするわけではありませんでした-コントローラーがそれ自体を閉じることができない場合がありました(ボタン「キャンセル」および「送信」はアクティブでしたが、アクションは処理されませんでした)。条件に応じて(親がコントローラーを開いた、アニメーションであったか、表示されなかったなど)。
  • 電子メールの受信者が追加されたかどうかにも違いはありませんでした。

だから、私の殺された5労働時間を発見したのは、代理人がいつか「解放」しているようだということです。電子メールコントローラーを他のモーダルコントローラーよりもモーダルとして開いている場合、その(以前のモーダル)コントローラーはガベージコレクターまたはその他の方法でクリーンアップされており、デリゲートもクリーンアップされていると考えられます(私は望みません詳細な掘り下げのためにさらに数時間を殺すために、私はそれをAppleの良心に任せます)。

とにかく、2つの言葉で、私の解決策は

「強力な」参照を使用してデリゲートオブジェクトをどこかに保持します。

私の場合、そのデリゲートの所有者はメインビューコントローラークラスでした(私の場合、ほとんどのアプリロジックがそれを使用しているため、これは常に使用可能です)。これは、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 に答える
2

これがどれほど関連性があるかはわかりませんが、別のモーダルビューコントローラーからメインビューコントローラーに戻った後、MFMailComposeViewController を表示しようとすると恐ろしい問題が発生しました。それはうまくいかないでしょう。メールコントローラーを起動する前に、この他のモーダルビューコントローラーを閉じようとしていましたが、私の解決策は呼び出さないことであることがわかりました:

[self dismissModalViewControllerAnimated:YES];

しかし、代わりに呼び出すには:

[self dismissModalViewControllerAnimated:NO];

次に、メール ビュー コントローラーを提示します。

私の場合、その1つの変更がすべての違いを生みました。これは sgosha が抱えていた問題に関連していると思われます。遅延を入れるのではなく、アニメーションをオフにするだけです (おそらく、アニメーションが完了するまで待っているだけです)。私にはフレームワークのバグのように見えます。

私はおそらくさらに説明する必要があります。メインのView Controllerに共有ボタンがあり、モーダルにテーブルビューをポップアップして、ユーザーが共有したいものを選択できるようにします。ここからメールをタップすると、UIActionSheet が表示され、メールに添付するファイルをさらに決定できます。

ミックス内の UIActionSheet が問題の原因になっている可能性があります。モーダル ビュー コントローラーの実際の解除は、メイン ビュー コントローラーのデリゲート メソッドで行われています。モーダル テーブル ビュー コントローラーを解除した後にメール ビュー コントローラーを起動しようとするのは、このメイン ビュー コントローラーです。

于 2012-04-08T17:05:55.223 に答える