MFMailComposeViewController代理方法没有被调用

3

我有一个类似操作表格的UIView,在其中点击一个按钮后调用了MFMailComposeViewController。虽然MFMailComposeViewController被成功地调用和呈现,但是当我点击取消时它并没有消失,有时还会崩溃。我知道这是一个已知的问题,但我已经尝试了所有已知的解决方法,但都不起作用。以下是我的代码:

SendFeedback.h:

#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>

@interface SendFeedback : UIView <UITableViewDelegate, UITableViewDataSource, MFMailComposeViewControllerDelegate, UINavigationControllerDelegate>

//Useless code to the problem.    

@property (nonatomic, retain) MFMailComposeViewController *feedBackComposer;

@end

SendFeedback.m:

- (void)baseInit
{
    //Useless code to the problem. 

    feedBackComposer = [[MFMailComposeViewController alloc] init];
    [feedBackComposer setMailComposeDelegate:self];
    [feedBackComposer setToRecipients:[NSArray arrayWithObject:@"info@getibox.com"]];
    [feedBackComposer setMessageBody:@"" isHTML:NO];
    [feedBackComposer setSubject:@"What I Love About iBox"];
}

调用composer的方法:

- (void)sendFeedbackComposer
{
    [self.window.rootViewController presentViewController:feedBackComposer animated:YES completion:nil];
}

关闭composer的方法:

- (void)mailComposeController:(MFMailComposeViewController *)feedBackComposer didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    //This method doesn't get called.

    [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];

    NSLog(@"Error: %@", error);
}
编辑: 所有在此问题中提供的答案都是正确的,而且这是我的错误。我想要做的是:我有一个包括UITableViewUINavigationController,其中一个cell应该通过在其上添加一个作为subview的操作表格(也是一个UITableView)来触发操作,就像之前的那个,这个视图也包括cells,其中之一会执行一个操作并调用MFMailComposeViewController,它被调用了但是退出时没有成功,即使我已经设置了它的代理和所有方法都是正确的,问题的原因是调用MFMailComposeController的方式,我首先从父视图中删除了那个小的UITableView,然后呈现MFMailComposeController,所以当我关闭邮件编辑器时,它会崩溃而不会给出结果,这让我把崩溃的原因与委托方法混淆了,愚弄了我。 以下是代码:
- (void)removeView
{
    if (self) {
        [UIView animateWithDuration:0.3
                         animations:^{backgroundView.alpha = 0;}
                         completion:^(BOOL finished){

        [UIView animateWithDuration:.3
                         animations:^{self.frame = CGRectMake(0, 568, 320, 568);}
                         completion:^(BOOL finished){[self removeFromSuperview];}];
        }];
    }
}
- (void)sendFeedbackComposer
{
    feedBackComposer = [[MFMailComposeViewController alloc] init];
    [feedBackComposer setMailComposeDelegate:self];
    [feedBackComposer setToRecipients:[NSArray arrayWithObject:@"info@getibox.com"]];
    [feedBackComposer setMessageBody:@"" isHTML:NO];
    [feedBackComposer setSubject:@"What I Love About iBox"];

    [self.window.rootViewController presentViewController:self.feedBackComposer animated:YES completion:nil];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    switch (indexPath.row) {
        case 2: //That's the index of the MailComposer caller.
            [self removeView];
            [self sendFeedbackComposer];
            break;
        case 6:
            [self removeView];
            break;
        default:
            break;
    }
}
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    [feedBackComposer.presentingViewController dismissViewControllerAnimated:YES completion:nil];

    NSLog(@"Error: %@", error);
}

感谢 Stefan Atanasov、Jim 和 Vitaly S.

那个 sendFeedbackComposer 方法是从其他类中调用的吗? - Robert
不是,它来自同一个类,是一个UIView。 - Abdelrahman Eid
这个类中实现的其他委托是否正常工作? - Robert
是的,UITableViewDelegate就是一个代理,而且使用起来非常简单。 - Abdelrahman Eid
4个回答

3

你确定代理方法没有被调用吗?我进行了测试并且它被调用了,但是要关闭邮件发送界面请使用以下代码:

[feedBackComposer dismissViewControllerAnimated: YES completion: nil];

此外,在视图实现中实现代理方法而不是在视图控制器中实现非常奇怪。


是的,它在 UIViewController 中可以工作,但在 UIView 中却不行,我不知道为什么,我使用了你的代码,结果也一样。我将解释我想要实现的内容:我有一个包含一个按钮的 UIViewController,该按钮将该 UIView 添加为子视图,就像操作表一样,然后该 UIView 中的一个按钮应该调用 MFMailComposeViewController,这就是为什么我想从 UIView 而不是 UIViewController 中执行它的原因,如果有其他建议,请告诉我。 - Abdelrahman Eid

2

补充Vitaly S.的回答(由于声望不够,我无法直接评论,抱歉)-委托方法已经被调用,所以问题在于解散。你可以尝试这个:

[feedBackComposer.presentingViewController dismissViewControllerAnimated: YES completion: nil];

1
但问题不在于解雇,而在于方法本身;它没有被调用,不确定是因为它是一个Subclass UIView还是其他原因,但奇怪的是其他委托方法如UITableViewDelegate可以轻松地被调用和使用。 - Abdelrahman Eid
嗯,奇怪 - 我用你的代码做了一个简单的测试项目 - 委托方法第一次被调用,composer没有被解散,之后它再也没有被调用过(但仍然被调用了一次)。 - Stefan Atanasov
奇怪的是,为什么方法被调用了,但作曲家没有被解雇?对我来说,它从来没有被调用过,有时当我点击取消时它什么也不做,而有时它会崩溃。 - Abdelrahman Eid
说实话,我不知道 - 这是测试项目,基本上是你的代码,所以可能问题出在其他地方 https://github.com/StefanAtanasov/MailComposerTest - Stefan Atanasov
你的代码有效!我不知道我做错了什么,我现在会调查并通知你。 - Abdelrahman Eid
这都是我的错,我做了一些导致出现问题的事情,请编辑您的答案并在其中添加评论以供我接受答案,我现在会解释我所做的事情。谢谢! - Abdelrahman Eid

1
委托方法需要从视图控制器中调用,而不是从UIView内部调用。
调用UIView的视图控制器将拥有您的代表。
<UITableViewDelegate, UITableViewDataSource, MFMailComposeViewControllerDelegate, UINavigationControllerDelegate>

在它的头文件中。

您需要创建一个委托方法,将信息从UIView传递给控制器,然后调用邮件和表格委托方法。

这里有一个链接,展示了如何使用委托协议从UIView触发视图控制器中的方法。

从其视图中触发UIViewController中的方法

希望这能帮到您,Jim


哦,我也猜到了!但是为什么<UITableViewDelegate, UITableViewDataSource>会被成功调用和使用呢?此外,这个UIView是一个subclass,而不是UIViewControllerUIView,我还能触发UIViewController中的方法吗?谢谢你的回答。 - Abdelrahman Eid

0

你需要检查设备是否配置了发送邮件,通过检查MFMailComposeViewController是否可响应来确定。

  if([MFMailComposeViewController canSendMail]){
  //your code
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接