MFMailComposeViewController аварийно завершает работу при попытке редактирования тела письма в iOS 5

У меня есть приложение, которое поддерживает как iOS 5, так и iOS 6. MFMailComposeViewController отлично работает в iOS 6, но у меня происходит сбой в iOS 5, когда пользователь пытается отредактировать тело письма. Все остальные поля редактируются без проблем. Кто-нибудь видел эту проблему?

Код выглядит следующим образом:

// Displays an email composition interface inside the application. Populates all the Mail fields.
-(void)displayMailComposerSheet {
    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
    picker.mailComposeDelegate = self;

    [picker setSubject:@"xyz"];

    NSArray *toRecipients = [NSArray arrayWithObject:@"[email protected]"];
    [picker setToRecipients:toRecipients];

    [picker setMessageBody:@"xyz" isHTML:NO];

    // Deprecated in iOS 6.0:
    [self presentModalViewController:picker animated:YES];
}

// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the 
// message field with the result of the operation.
- (void)mailComposeController:(MFMailComposeViewController*)controller 
          didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {

    // Deprecated in iOS 6.0:
    [self dismissModalViewControllerAnimated:YES];
}

Журнал сбоев выглядит следующим образом:

Crashed Thread:  0

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000

Application Specific Information:
iPhone Simulator 358.4, iPhone OS 5.1 (iPhone/9B176)

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MFComposeTextContentView setInputAccessoryView:]: unrecognized selector sent to instance 0x8d6b880'
*** First throw call stack:
(0x1da6022 0x1b19cd6 0x1da7cbd 0x1d0ced0 0x1d0ccb2 0x5e4b1 0xb5aa29 0x1d71855 0x1d71778 0xa9f19a 0xaabb03 0x49e084 0x169a798 0x4658fb 0x4675f8 0x45fe29 0x45f133 0x4603bf 0x462a21 0x46297c 0x45b3d7 0x1c01a2 0x1c0532 0x1a6dc4 0x19a634 0x1f39ef5 0x1d7a195 0x1cdeff2 0x1cdd8da 0x1cdcd84 0x1cdcc9b 0x1f387d8 0x1f3888a 0x198626 0x303d 0x2f65)

abort() called

Thread 0 Crashed:
0   libsystem_kernel.dylib          0x99b6e9c6 __pthread_kill + 10
1   libsystem_c.dylib               0x991a5f78 pthread_kill + 106
2   libsystem_c.dylib               0x99196bdd abort + 167
3   libc++abi.dylib                 0x027dee78 abort_message + 50
4   libc++abi.dylib                 0x027dc89e _ZL17default_terminatev + 34
5   libobjc.A.dylib                 0x01b19f17 _objc_terminate + 94
6   libc++abi.dylib                 0x027dc8de _ZL19safe_handler_callerPFvvE + 13
7   libc++abi.dylib                 0x027dc946 std::terminate() + 23
8   libc++abi.dylib                 0x027ddb3e __cxa_rethrow + 83
9   libobjc.A.dylib                 0x01b19e15 objc_exception_rethrow + 47
10  CoreFoundation                  0x01cdcde0 CFRunLoopRunSpecific + 304
11  CoreFoundation                  0x01cdcc9b CFRunLoopRunInMode + 123
12  GraphicsServices                0x01f387d8 GSEventRunModal + 190
13  GraphicsServices                0x01f3888a GSEventRun + 103
14  UIKit                           0x00198626 UIApplicationMain + 1163
15  SomeXYZApp                      0x0000303d main + 141 (main.m:16)
16  SomeXYZApp                      0x00002f65 start + 53

person Sergio    schedule 21.10.2012    source источник
comment
Просто поясню, что MFComposeTextContentView — это объект внутри MFMailComposeViewController. Экземпляр 0x8d6b880 действительно является MFComposeTextContentView. По какой-то причине получает селектор setInputAccessoryView, который вызывает сбой. Все это происходит внутри класса MFMailComposeViewController.   -  person Sergio    schedule 21.10.2012


Ответы (4)


1 Создайте учетную запись электронной почты, если вы пытаетесь сделать это на устройстве

2 MFMailComposeViewController содержит метон "canSendMail, поэтому вы можете попробовать:

if ([MFMailComposeViewController canSendMail]) {
 // create mail
} else {
// error message
}

3 Попробуйте вызвать контроллер в основном потоке:

dispatch_async(dispatch_get_main_queue(), ^{
    //call MFMailComposeViewController
});
person edzio27    schedule 21.10.2012
comment
Шаги 1 и 2 уже являются частью моего кода. Пробовал шаг 3, но без изменений. Я получаю представление MailCompose, сбой происходит при попытке отредактировать тело электронной почты, как если бы первый ответивший был отправлен на неправильный объект. - person Sergio; 21.10.2012

Была такая же проблема. Только в IOS6, не в IOS5.1. При тестировании выяснилось, что форма не была выпущена должным образом. Поэтому я добавил код для принудительного освобождения формы. Это сработало в моем случае. Надеюсь, это поможет и вам.

-(void) sendMail:(NSString *) mailTo
{
    // Check if you can send an e-mail
    if ([MFMailComposeViewController canSendMail])
    {
        @try
        {
            // show the form
            MFMailComposeViewController *mailForm = nil;
            mailForm = [[MFMailComposeViewController alloc] init];
            mailForm.mailComposeDelegate = self;
            [mailForm setToRecipients:@[ mailTo ]];
            mailForm.modalPresentationStyle = UIModalPresentationFormSheet;
            mailForm.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
            [self presentModalViewController:mailForm animated:YES];
        }

        @catch (NSException *exception)
        {
            // Show what went wrong
            NSString *fout = [[NSString alloc] initWithFormat:@"%@: %@",[exception name], [exception reason]];
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Mailer" message:fout delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
        }
    }
    else
    {
        // Inform the user you cannot send mail, no mailbox set
        [self noEmailAccountMeansNoEmail];
    }
}

- (void)mailComposeController:(MFMailComposeViewController*)mailForm didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    // Get the mail form off the screen 
    if ((mailForm != nil))
        [mailForm dismissModalViewControllerAnimated:YES];

    // Force release/dealloc of the screen
    mailForm = nil;
    return;
}
person objectivekc    schedule 15.01.2013

Попробуйте еще раз, может быть, вы забыли мелочь... я не уверен в этом... ваш код выглядит нормально.... он должен работать...

Сначала добавьте и импортируйте MessageUI Framework

#import <MessageUI/MessageUI.h>

и объявить MFMaileComposeViewControllerDelegate

@interface MailViewController : UIViewController <MFMailComposeViewControllerDelegate>

Напишите этот код для отправки почты

- (IBAction)openMail:(id)sender 
{
if ([MFMailComposeViewController canSendMail])
{
    MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];

    mailer.mailComposeDelegate = self;

    [mailer setSubject:@"xyz"];

    NSArray *toRecipients = [NSArray arrayWithObjects:@"[email protected]", @"[email protected]", nil];
    [mailer setToRecipients:toRecipients];

    NSString *emailBody = @"xyz";

    [mailer setMessageBody:emailBody isHTML:NO];

    [self presentModalViewController:mailer animated:YES];

    [mailer release];
}
else
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failure"
                                                    message:@"Your device doesn't support the composer sheet"
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles: nil];
    [alert show];
    [alert release];
}

}

а также напишите метод делегата MFMailComposeViewControllerDelegate

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error 
{   
    switch (result)
    {
        case MFMailComposeResultCancelled:
            NSLog(@"Mail cancelled: you cancelled the operation and no email message was queued.");
            break;
        case MFMailComposeResultSaved:
            NSLog(@"Mail saved: you saved the email message in the drafts folder.");
            break;
        case MFMailComposeResultSent:
            NSLog(@"Mail send: the email message is queued in the outbox. It is ready to send.");
            break;
        case MFMailComposeResultFailed:
            NSLog(@"Mail failed: the email message was not saved or queued, possibly due to an error.");
            break;
        default:
            NSLog(@"Mail not sent.");
            break;
    }

        // Remove the mail view
    [self dismissModalViewControllerAnimated:YES];
}
person Wolverine    schedule 21.10.2012
comment
Неа. Это в основном то, что у меня есть. Как я упоминал ранее, у меня отображается представление MailComposer. Таким образом, все проверки и противовесы были сделаны. Я могу нажать на все записи в представлении, кроме тела письма. Я даже могу отправить электронное письмо, если тело не изменилось. Приложение вылетает только при попытке отредактировать тело, и это происходит только на устройствах под управлением iOS 5. - person Sergio; 21.10.2012
comment
в теле вашего электронного письма.......что вы показываете........? это HTML или простой текст....? - person Wolverine; 22.10.2012
comment
Я показываю простой текст. Изменение настройки HTML не меняет результат сбоя. И да, я использую ARC. - person Sergio; 22.10.2012

Я нашел проблему. Я использую DAKeyboardControl, который позволяет прокручивать клавиатуру (см. GitHub для KeyboardControl DA).

Когда responseerDidBecomeActive в коде DA вызывается через MFMailComposeViewController, textField получает объект MFComposeTextContentView, который не отвечает на inputAccessoryView. Кажется, это взаимодействие, которое не поддерживается. Однако обратите внимание, что в iOS 6 эта проблема не возникает, поскольку перегруженные классы DA не вызываются MFMailComposeViewController.

Если убрать поддержку DAKeyboardControl, все работает корректно.

person Sergio    schedule 27.10.2012
comment
Последняя версия кода Дэниела устраняет эту проблему. Спасибо Даниэль! - person Sergio; 28.10.2012