【问题标题】:MFMailComposeViewController crash in iOS6 ARCiOS6 ARC 中的 MFMailComposeViewController 崩溃
【发布时间】:2013-06-12 04:43:12
【问题描述】:

我正在从我的自定义类(不是 viewController)中呈现 MFMailComposeViewController。在 iOS5 中它工作正常,但在 iOS6 中它在呈现撰写表后立即崩溃。我发现了问题dealloc 方法在呈现视图后被调用,因此 self 正在释放。由于这个 mailcomposer 不能调用 self 的委托方法,所以它崩溃了。我没有得到解决方案。我正在使用 ARC如何防止 self 在委托方法被调用之前解除分配?

  -(void)shareOnViewController:(UIViewController *)viewController  completion:(ShareCompletionHandler)completion
{

  if ([MFMailComposeViewController canSendMail]) {

    MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
    mailer.mailComposeDelegate = self;
    mailer.modalPresentationStyle = UIModalPresentationPageSheet;
    [mailer setSubject:[self.userInfo objectForKey:@"title"]];

    NSData *imageData = UIImagePNGRepresentation([self.userInfo objectForKey:@"image"]);
    if (imageData) {
        [mailer addAttachmentData:imageData mimeType:@"image/png" fileName:@"AttachedImage"];
    }


    NSURL *emailBody = [self.userInfo objectForKey:@"url"];
    if (![emailBody isEqual:@""]) {
        [mailer setMessageBody:[emailBody absoluteString] isHTML:NO];
    }

    [viewController presentModalViewController:mailer animated:YES];

   } else {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unable to send mail"
                                                    message:@"Device is not configured to send mail"
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
   }

self.completionHandler = completion;

}

【问题讨论】:

  • 请确保其他类保持您的self(或自定义类)处于活动状态,直到MFMailComposeViewController 被正确关闭。谁拥有您的 self(或自定义类)?
  • @Anil 也许你找到了解决方案?同样的问题...
  • @ElisabettaFalivene 为了防止委托对象解除分配,必须牢牢抓住它。我在控制器上创建了一个属性,该属性很可能始终存在以保存委托对象。要明确假设 Ais 控制器 B 是呈现 Mail composer 并委托给 .我在控制器 A 中保留了 B 的引用

标签: ios objective-c mfmailcomposeviewcontroller


【解决方案1】:

据我所知,presentModalViewController 方法在 iOS 6.0 中已弃用。

你需要使用

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion 

你还能显示崩溃日志吗??

【讨论】:

  • 我都试过了......同样的问题......发送到释放实例的崩溃日志方法
  • 崩溃日志显示您正在尝试调用未实现的方法。通过该方法更改,我能够成功地在 iOS 6.1 中显示邮件控制器。可能是您的完成处理程序未正确调用。检查是否正确。
  • 我没有调用任何方法,mailcomposeViewController 调用它的委托方法,时间委托(自我)被释放。 [RSEmailService respondsToSelector:]:消息发送到已释放实例 0x9c91600
  • 你想用'self.completionHandler = completion;'做什么
  • 稍后我需要该完成块与委托方法一起使用。问题不在于完成块
【解决方案2】:
  if ([MFMailComposeViewController canSendMail]) {
        MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc]
                                                     init];

    NSData *imageData = UIImagePNGRepresentation(image);
    mailComposer.mailComposeDelegate = self;
    [mailComposer setSubject:subject];
    NSArray * recipents = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%@",NSLocalizedString(@"client_email", @"")],nil];

    [mailComposer setToRecipients:recipents];

    [mailComposer addAttachmentData:imageData mimeType:@"image/png" fileName:[NSString stringWithFormat:@"imageProfile-%@-%@",someId,lastname]];



    mailComposer.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;

    [vc presentViewController:mailComposer animated:YES completion:nil];
}
else
{
    UIAlertView *tmp = [[UIAlertView alloc]
                        initWithTitle:@"Email Account Not Found"
                        message:@"You need to setup an Email Account!"
                        delegate:self
                        cancelButtonTitle:nil
                        otherButtonTitles:@"Ok", nil];

    [tmp show];
}

【讨论】:

    【解决方案3】:

    可能的根本原因之一是 ARC。

     MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
    

    mailer 将在方法主体完全执行后立即自动释放。

    您可以创建一个引用来保存对象以避免 ARC 在它准备好之前释放它。

    @property (nonatomic, strong) MFMailComposeViewController * composer;
    ....
    
    
    self.composer = [[MFMailComposeViewController alloc] init];
    ...
    [viewController presentViewController:self.composer animated:YES];
    

    [编辑建议]

    抱歉,我错过了您从另一个自定义类调用方法的问题的第一部分。

    我也遇到过类似的情况。最后,我将“自定义类”转换为单例类。

    #pragma mark Singleton Methods
    
    + (id)sharedInstance {
        static CustomClass *sharedInstance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedInstance = [[self alloc] init];
        });
        return sharedInstance;
    }
    

    这将确保类被很好地保留。但这将取决于 CustomClass 的使用和设计。只是为了分享我所做的。

    [[CustomClass sharedInstance] shareOnViewController:vc completion:...];
    

    【讨论】:

    • 我认为 OP 的问题不在于 mailer 对象,而在于 selfMFMailComposeViewController 对象的代表。另一方面,mailer 在范围用完之前不会被释放,所以这足够安全。
    • @holex:如果项目不使用 ARC,则不会发布邮件。但是,在 ARC 设置下,在功能范围内创建的变量将在功能块完成后立即自动释放(除非它被引用保留)。
    • ARC 中,如果在范围用完后没有任何东西使对象保持活动状态,它将被释放。如果您将该 local 邮件控制器添加到范围内的另一个控制器,以使其保持活动状态,即使您不再关心它。因此你不需要让它活着,即使是通过公共财产。我说的是它的delegate 发布得太早了,因此邮件程序无法回调任何对象。
    • @holex 谢谢,我明白你的意思了。我没有意识到他的问题是从另一个自定义类调用该方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 2012-10-17
    相关资源
    最近更新 更多