2010-11-01 1 views
4

Я отображающее MFMailComposeViewController так:Отклонив в MFMailComposeViewController вызывает EXC_BAD_ACCESS

- (IBAction) contactUs: (id) sender { 
    [Tracker trackContactUsPressed: [MFMailComposeViewController canSendMail]]; 

    if ([MFMailComposeViewController canSendMail] == NO) { 
     UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Email Error" 
                 message: @"Email has not been configured on this device. Please send us an email at\[email protected]" 
                 delegate: self 
               cancelButtonTitle: @"OK" 
               otherButtonTitles: nil]; 
     [alert show]; 
     [alert release]; 
    } else { 

     MFMailComposeViewController *controller = [[[MFMailComposeViewController alloc] init] autorelease]; 

     [controller setSubject:@"Comments about FOO"];    

     [controller setToRecipients: [NSArray arrayWithObject: @"[email protected]"]]; 
     [controller setMailComposeDelegate: self]; 

     [[self parentViewController] presentModalViewController:controller animated:YES]; 
    } 
} 

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

- (void) mailComposeController: (MFMailComposeViewController *) controller didFinishWithResult: (MFMailComposeResult) result error: (NSError *) error { 
    [[self parentViewController] dismissModalViewControllerAnimated: YES]; 
} 

Однако как только делегат называется, и вид исчезает, я получаю EXC_BAD_ACCESS. Обратный ход говорит следующее:

#0 0x00000000 in ??() 
#1 0x0065a2d9 in -[UIWindowController transitionViewDidComplete:fromView:toView:]() 
#2 0x0044a905 in -[UITransitionView notifyDidCompleteTransition:]() 
#3 0x003f1499 in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]() 
#4 0x003f132b in -[UIViewAnimationState animationDidStop:finished:]() 
#5 0x02631db0 in run_animation_callbacks() 
#6 0x02631c6f in CA::timer_callback() 
#7 0x0284bf73 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__() 
#8 0x0284d5b4 in __CFRunLoopDoTimer() 
#9 0x027a9dd9 in __CFRunLoopRun() 
#10 0x027a9350 in CFRunLoopRunSpecific() 
#11 0x027a9271 in CFRunLoopRunInMode() 
#12 0x0305500c in GSEventRunModal() 
#13 0x030550d1 in GSEventRun() 
#14 0x003cfaf2 in UIApplicationMain() 
#15 0x000023c5 in main (argc=1, argv=0xbfffefcc) at main.m:14 

Я не могу понять, что случилось. Насколько я знаю, это работало ранее с SDK 3.x, который мы использовали (мы выпустили его и все!). Теперь с новым SDK (4.1) он, похоже, терпит неудачу. Я не уверен, что это связано.

Кто-нибудь знает, что случилось?

ответ

8

Я нашел проблему.

Мы используем библиотеку под названием ShareKit для интеграции с Twitter и Facebook. Поскольку у нас уже была собственная электронная почта, нам не нужен ShareKit, чтобы обрабатывать ее для нас, поэтому мы удалили файлы обработки электронной почты ShareKit.

Все было хорошо, за исключением того, что в его инициализации, ShareKit делает это:

SHKSwizzle([MFMailComposeViewController class], @selector(viewDidDisappear:), @selector(SHKviewDidDisappear:)); 

Где SHKSwizzle в основном заменяет MFMailComposerViewController в viewDidDisappear: метод с SHKviewDidDisappear: (Не спрашивайте меня, почему ... Я думаю, что это ужасно).

Как бы то ни было, выясняется, что SHKviewDidDisappear был обработчиком почты ShareKit, поэтому удалял файл, как заставить код прыгать в гиперпространство и громить ужасно. Проблема с восстановлением файла снова устраняет проблему.

Ugh.

Спасибо всем за вашу помощь!

0

Вероятно, вы получаете автореализованный из-под вас. Я видел, как это происходит с UIDocumentInteractionController. Лучшим решением, вероятно, является сохранение MFMailComposeViewController в переменной экземпляра, а затем его выпуск в файле didFinishWithResult.

+0

Нет, удаление автореферата (и его утечка) по-прежнему вызывает такое же поведение. Поэтому я почти уверен, что это не связано с тем, что он выпущен преждевременно. –

+0

Вы пытались использовать NSZombies, чтобы узнать, что происходит заново? – makdad

1

Просто догадка, но то, что выглядит странно для меня эти строки:

[[self parentViewController] presentModalViewController:controller animated:YES]; 

и

[[self parentViewController] dismissModalViewControllerAnimated: YES]; 

Правда, я не знаю о вашем расположении контроллеров зрения, но ISN» Это немного необычно для ссылки на [self parentViewController] напрямую? Вы сильно связываете три контроллера вида (вызывающий, родительский и модальный); это препятствует повторному использованию контроллера кода/вида (например, если вы хотите повторно использовать один и тот же контроллер представления в другой иерархии представлений в другом месте приложения).

Единственная причина, по которой я могу представить, что вы можете это сделать, заключается в том, что родительский элемент является UINavigationController/UITabBarController, и поскольку это верхний вид, вы хотите, чтобы этот контроллер представления представлял модальный.

В этом случае я использую:

[[self navigationController] presentModalViewController:controller animated:YES]

Или еще лучше, в ситуации Tab Bar, у меня есть мой вид корневой контроллер зарегистрировать наблюдателя прослушивания уведомлений, а затем все модальности запускаются из контроллер корневого представления.

Могу ли я получить дополнительную информацию о стеке просмотров? Кроме того, вы могли бы однажды попытаться просто призывать «я» вместо родителя и посмотреть, что происходит?

+0

Мой оригинальный код вызывал его сам, и он тоже не удался. Код, который я вставил, вызывает parentViewController только потому, что я пытался выяснить, может ли это быть проблемой (это было не так, я просто забыл вернуть изменение). –

+0

ОК - одна идея вниз. Пробовали ли вы установить NSZombieEnabled = YES в разделе переменных окружения исполняемого файла, чтобы мы могли видеть, что происходит завышенным? Обычно в случае EXC_BAD_ACCESS это поможет вам. – makdad

+0

Включение NSZombieEnabled не помогает. Это не похоже на то, что EXC_BAD_ACCESS исходит из перевыпущенной ссылки. Обратный след почти выглядит так, как будто мы пытаемся вызвать нулевой метод каким-то образом ... –

0

Если вы хотите, чтобы закрыть почтовый композитор, лучший способ сделать это, как этот

- (void) mailComposeController: (MFMailComposeViewController *) controller didFinishWithResult: (MFMailComposeResult) result error: (NSError *) error 
{ 
    [controller dismissModalViewControllerAnimated: YES]; 
} 

Таким образом, вам не нужно беспокоиться о контроллере или его родителя или что-нибудь

, а также для представляя композитор, Вместо использования

[[self parentViewController] presentModalViewController:controller animated:YES]; 

попробовать с помощью

[self presentModalViewController:controller animated:YES];