MFMailComposeViewController在iOS5中dismissModalViewControllerAnimated时崩溃
我在我的conde使用MFMailComposeViewController来提供邮件function,但发送邮件或当我想取消邮件后,它将崩溃。
下面是我的代码:
(IBAction)FnForPlutoSupportEmailButtonPressed:(id)sender { { if ([MFMailComposeViewController canSendMail]) { MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init]; mailer.mailComposeDelegate = self; [mailer setSubject:@"Need help from Pluto support team"]; NSArray *toRecipients = [NSArray arrayWithObjects:@"support@myplu.to",nil]; [mailer setToRecipients:toRecipients]; NSString *emailBody = @""; [mailer setMessageBody:emailBody isHTML:NO]; //mailer.modalPresentationStyle = UIModalPresentationPageSheet; [self presentModalViewController:mailer animated:YES]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failure" message:@"Your device doesn't support the composer sheet" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; [alert show]; } } } (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { // Notifies users about errors associated with the interface switch (result) { case MFMailComposeResultCancelled: break; case MFMailComposeResultSaved: break; case MFMailComposeResultSent: break; case MFMailComposeResultFailed: break; default: break; } [self dismissModalViewControllerAnimated:YES]; }
我已经阅读了所有的博客文章,但没有find解决办法, 这篇博文是关于这个有很好的解释,但根据这个我不介绍我的视图控制器在viewdidload或viewdidappear。
我正在获取EXE_BAD_ACCESS,以下是崩溃日志:
**
> #0 0x00000000 in ?? () > #1 0x01dc5aa4 in -[UIViewController _setViewAppearState:isAnimating:] () > #2 0x01dc5f47 in -[UIViewController __viewDidDisappear:] () > #3 0x01dc6039 in -[UIViewController _endAppearanceTransition:] () > #4 0x01dd2e7e in -[UIViewController(UIContainerViewControllerProtectedMethods) endAppearanceTransition] () > #5 0x01fc8de1 in -[UIWindowController transitionViewDidComplete:fromView:toView:] () > #6 0x01da334b in -[UITransitionView notifyDidCompleteTransition:] () > #7 0x01da3070 in -[UITransitionView _didCompleteTransition:] () > #8 0x01da531b in -[UITransitionView _transitionDidStop:finished:] () > #9 0x01d23fb6 in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] () > #10 0x01d24154 in -[UIViewAnimationState animationDidStop:finished:] () > #11 0x0163bbce in CA::Layer::run_animation_callbacks () > #12 0x03664fe4 in _dispatch_client_callout () > #13 0x03655997 in _dispatch_main_queue_callback_4CF () > #14 0x012c03b5 in __CFRunLoopRun () > #15 0x012bf804 in CFRunLoopRunSpecific () > #16 0x012bf6db in CFRunLoopRunInMode () > #17 0x030f1913 in GSEventRunModal () > #18 0x030f1798 in GSEventRun () > #19 0x01ce82c1 in UIApplicationMain ()
**
根据iOS 5的更新文件,他们提到:
presentModalViewController:animation:
呈现由给定视图控制器pipe理的用户的模式视图。 (不推荐使用presentViewController:animated:completion:
。
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated Parameters
取消接收者呈现的视图控制器。 (不build议使用dismissViewControllerAnimated:completion:
。
- (void)dismissModalViewControllerAnimated:(BOOL)animated
我也试过,但它仍然崩溃
你需要在你的类中保留对MFMailComposeViewController * mailer的强有力的引用,并且在你closures它之后,你可以清空那个引用。 问我怎么知道这个:-)
@implememtation MyClass { MFMailComposeViewController *mailer; } ... (IBAction)FnForPlutoSupportEmailButtonPressed:(id)sender { { if ([MFMailComposeViewController canSendMail]) { /* USE IVAR */mailer = [[MFMailComposeViewController alloc] init];
稍后,当完成它时,您只需“邮件=零;” 释放它。
编辑:我所做的build议是使用一个块到主队列来执行释放。 如果你只是使用'self.mailer = nil',那么释放发生在最终的委托方法完成后,你肯定不再使用它。
编辑2:这种崩溃不会一直发生在所有的设备上 – 我会说它在你收到最终的委托方法和完成工作之间的竞争状态。 苹果公司并没有提供任何关于参考的方法 – 但是,苹果公司产品的一般做法是假定你得到的任何对象都是通过一个runLoop“借出”的,然后如果你想保留一个参考,你必须保留对象。
如果你的代码已经在你的代码中实现了SHK.m并且改变了
[[currentView parentViewController] dismissModalViewControllerAnimated:YES];
至
[currentView dismissModalViewControllerAnimated:YES];
这将解决您的问题。
感谢大家的回应。
也评论这些线
SHKSwizzle([MFMailComposeViewController class], @selector(viewDidDisappear:), @selector(SHKviewDidDisappear:)); if (NSClassFromString(@"MFMessageComposeViewController") != nil) SHKSwizzle([MFMessageComposeViewController class], @selector(viewDidDisappear:), @selector(SHKviewDidDisappear:));
您好,您可以使用下面的代码发送邮件的应用程序将不会发送任何电子邮件表格模拟器,你必须在设备上安装应用程序。 当您尝试访问它们不在内存中的对象时,EXE_BAD_ACCESS会出现,重新设置设备区分大小写。
-(void)sendMail:(id)sender { //create instance of class at runtime. Class mailComposer = (NSClassFromString(@"MFMailComposeViewController")); if (mailClass != nil) { // check the current device is configured for sending emails //if it is not configured for mail you open mail application on device. if ([mailClass canSendMail]) { [self displayComposerSheet]; } else { [self launchMailAppOnDevice]; } } else { [self launchMailAppOnDevice]; } } -(void)displayComposerSheet { MFMailComposeViewController *mailPicker = [[MFMailComposeViewController alloc] init]; picker.mailComposeDelegate = self; [picker setSubject:@"Welcome!"]; //recipients NSArray *to = [NSArray arrayWithObject:@"jhon@example.com"]; [picker setToRecipients:toRecipients]; // Attach an image NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Default" ofType:@"png"]; NSData *imageData = [NSData dataWithContentsOfFile:filePath]; [picker addAttachmentData:myData mimeType:@"image/png" fileName:@"Default"]; // Set email body text //NSString *emailBody = @"......!"; //[picker setMessageBody:emailBody isHTML:NO]; [self presentModalViewController:picker animated:YES]; [picker release]; } - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult: (MFMailComposeResult)result error:(NSError*)error { message.hidden = NO; // Notifies users about errors associated with the interface switch (result) { case MFMailComposeResultCancelled: message.text = @"Canceled"; break; case MFMailComposeResultSaved: message.text = @"Saved"; break; case MFMailComposeResultSent: message.text = @"Sent"; break; case MFMailComposeResultFailed: message.text = @"Failed"; break; default: message.text = @"Not sent"; break; } [self dismissModalViewControllerAnimated:YES]; } -(void)launchMailAppOnDevice { NSString *recipients = @""; NSString *body = @""; NSString *email1 = [NSString stringWithFormat:@"%@%@", recipients, body]; email1 = [email1 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; [[UIApplication sharedApplication] openURL:[NSURL URLWithString:email1]]; }
由于栈的停止是0x00000000
,我假设UIKit内的一些代码跳转到一个零函数指针。 启用僵尸,看看你是否得到僵尸对象访问错误。 (编辑您的项目计划,在运行/debugging,诊断选项卡下,选中“启用僵尸对象”)
试试这个代码,这个效果很好,没有崩溃..联系我们的方法是button目标select器..
-(void)ContactUs:(UIButton*)button { 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]; } else { [self launchMailAppOnDevice]; } } else { [self launchMailAppOnDevice]; } } -(void)displayComposerSheet { MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init]; picker.mailComposeDelegate = self; //[picker setSubject:@"Hello from California!"]; // Set up recipients NSArray *toRecipients = [NSArray arrayWithObject:@"info@imp.co.in"]; //NSArray *ccRecipients = [NSArray arrayWithObjects:@"second@example.com", @"third@example.com", nil]; //NSArray *bccRecipients = [NSArray arrayWithObject:@"fourth@example.com"]; [picker setToRecipients:toRecipients]; //[picker setCcRecipients:ccRecipients]; //[picker setBccRecipients:bccRecipients]; // Attach an image to the email /*NSString *path = [[NSBundle mainBundle] pathForResource:@"rainy" ofType:@"png"]; NSData *myData = [NSData dataWithContentsOfFile:path]; [picker addAttachmentData:myData mimeType:@"image/png" fileName:@"rainy"];*/ // Fill out the email body text //NSString *emailBody = @"It is raining in sunny California!"; //[picker setMessageBody:emailBody isHTML:NO]; [self presentModalViewController:picker animated:YES]; [picker release]; } - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { message.hidden = NO; // Notifies users about errors associated with the interface switch (result) { case MFMailComposeResultCancelled: message.text = @"Canceled"; break; case MFMailComposeResultSaved: message.text = @"Saved"; break; case MFMailComposeResultSent: message.text = @"Sent"; break; case MFMailComposeResultFailed: message.text = @"Failed"; break; default: message.text = @"Not sent"; break; } [self dismissModalViewControllerAnimated:YES]; } -(void)launchMailAppOnDevice { NSString *recipients = @""; NSString *body = @""; NSString *email1 = [NSString stringWithFormat:@"%@%@", recipients, body]; email1 = [email1 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; [[UIApplication sharedApplication] openURL:[NSURL URLWithString:email1]]; }
如果您正在使用ARC,控制器对象在释放之前已经释放。
除了堆栈分配的variables之外,保留对象。
你有没有在.h文件中设置委托MFMailComposeViewControllerDelegate。 过去我曾遇到这样的问题。 而错误是非常小的。 请检查委托在.h文件中。