はい!やった!信じられませんが、問題は解決しました!これは以下に関連しています:
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
率直に言って、コードはちょっと厄介ですが、これは単なる一般的な考えです。私はあなたがあなた自身をもっとうまく管理することを願っています。
幸運と神はマイクロソフトを祝福します!^^