Сбой iPhone при представлении контроллера модального представления
-
05-07-2019 - |
Вопрос
Я пытаюсь отобразить модальный вид сразу после того, как другой вид был представлен модально (второй - это вид загрузки, который появляется).
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Show load
LoadViewController *loader = [[LoadViewController alloc] init];
[self presentModalViewController: loader animated:NO];
[loader release];
}
Но когда я делаю это, я получаю "Принятый программой сигнал:"EXC_BAD_ACCESS"." ошибка.
Трассировка стека - это:
0 0x30b43234 in -[UIWindowController transitionViewDidComplete:fromView:toView:]
1 0x3095828e in -[UITransitionView notifyDidCompleteTransition:]
2 0x3091af0d in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]
3 0x3091ad7c in -[UIViewAnimationState animationDidStop:finished:]
4 0x0051e331 in run_animation_callbacks
5 0x0051e109 in CA::timer_callback
6 0x302454a0 in CFRunLoopRunSpecific
7 0x30244628 in CFRunLoopRunInMode
8 0x32044c31 in GSEventRunModal
9 0x32044cf6 in GSEventRun
10 0x309021ee in UIApplicationMain
11 0x00002154 in main at main.m:14
Есть какие-нибудь идеи?Я в полном замешательстве!Загрузочный вид пуст, так что там определенно ничего не происходит, что вызывает ошибку.Это как-то связано с запуском 2 представлений модально в одном цикле событий или что-то в этом роде?
Спасибо,
Майк
Редактировать:Очень странно...Я немного изменил его, чтобы вид загрузки отображался с небольшой задержкой, и это работает нормально!Таким образом, похоже, что это что-то внутри одного и того же цикла событий!
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Show load
[self performSelector:@selector(doit) withObject:nil afterDelay:0.1];
}
- (void)doit {
[self presentModalViewController:loader animated:YES];
}
Решение
Я немного изменил его, чтобы вид загрузки отображался с небольшой задержкой, и это работает нормально!Таким образом, похоже, что это что-то внутри одного и того же цикла событий!
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Show load
[self performSelector:@selector(doit) withObject:nil afterDelay:0.1];
}
- (void)doit {
[self presentModalViewController:loader animated:YES];
}
Другие советы
Я полагаю, что воспроизвел ту же ошибку в iOS 4.В моем приложении сбой постоянно происходил при попытке показать второе модальное представление сразу после показа первого модального представления.Я боролся в течение нескольких часов, сходя с ума.
Прочитав сообщения в этой теме, я попытался создать простой воспроизводимый пример, используя шаблон приложения панели вкладок.Я смог использовать UIImagePickerController для отображения первого модального представления после ответа на нажатие кнопки в "FirstViewController.m".Когда я попытался снова показать UIImagePickerController (после обработки сообщения imagePickerControllerDidCancel), приложение завершило работу с той же ошибкой.
На устройстве просто не было никакой подсказки, что происходит.Однако, когда я запустил код в симуляторе, мне посчастливилось получить это сообщение на консоли:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempting to begin a modal transition from to while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear to know the current transition has completed'
Так что, похоже, мой единственный выбор - последовать совету сообщения об ошибке и просто дождаться появления viewDidAppear (используя флаг, указывающий, что я нахожусь в этом специальном режиме), а затем загрузить второе модальное представление.
Вот полная трассировка стека для полноты картины:
** Call stack at first throw: ( 0 CoreFoundation 0x0238c919 __exceptionPreprocess + 185 1 libobjc.A.dylib 0x024da5de objc_exception_throw + 47 2 CoreFoundation 0x02345078 +[NSException raise:format:arguments:] + 136 3 Foundation 0x000ab8cf -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116 4 UIKit 0x00544317 -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] + 212 5 UIKit 0x0035c769 -[UIViewController presentModalViewController:withTransition:] + 2937 6 TestTempDelete 0x000021cf -[FirstViewController showImagePicker] + 167 7 Foundation 0x0002fcea __NSFireDelayedPerform + 441 8 CoreFoundation 0x0236dd43 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19 9 CoreFoundation 0x0236f384 __CFRunLoopDoTimer + 1364 10 CoreFoundation 0x022cbd09 __CFRunLoopRun + 1817 11 CoreFoundation 0x022cb280 CFRunLoopRunSpecific + 208 12 CoreFoundation 0x022cb1a1 CFRunLoopRunInMode + 97 13 GraphicsServices 0x02bf12c8 GSEventRunModal + 217 14 GraphicsServices 0x02bf138d GSEventRun + 115 15 UIKit 0x002beb58 UIApplicationMain + 1160 16 TestTempDelete 0x00001eb4 main + 102 17 TestTempDelete 0x00001e45 start + 53
Надеюсь, это поможет.
** Как было сказано ранее, используйте isIgnoringInteractionEvents
//Check if the app is ignoring interatctions, if so, add a delay for 1 sec
if([[UIApplication sharedApplication] isIgnoringInteractionEvents]==TRUE) {
[currentViewController performSelector:@selector(presentModalViewController:animated:) withObject:screen afterDelay:1];
} else {
[currentViewController presentModalViewController:screen animated:YES];
}
Возможно, если вы получаете это после нажатия кнопки, которая была связана с вашим кодом в Interface Builder, у вас есть два действия, связанные с одной кнопкой (возможно, если у вас было модальное представление, связанное с кнопкой, затем вы продублировали кнопку и связали другое модальное представление).Это попытается отключить их оба, и поэтому с этим сообщением произойдет сбой.
Я столкнулся с таким же исключением
Завершение работы приложения из-за неперехваченного исключения 'NSInternalInconsistencyException', причина:"Попытка начать модальный переход от к, в то время как переход уже осуществляется.Дождитесь появления viewDidAppear / viewDidDisappear, чтобы узнать, что текущий переход завершен '
Как предлагалось ранее, я попытался отложить представление модального перехода, но на самом деле это не помогло.Затем я обнаружил, что у меня есть несколько IBActions, подключенных к событию touchUpInside моей кнопки!!!.В моем случае запустились бы два IBActions:модальное представление средства выбора людей и модальное представление средства выбора изображений.Это объясняет сообщение об ошибке.Проверьте, подключено ли у вас несколько IBActions!
Ваша проблема, скорее всего, в методе, который инициализирует и представляет метод, в котором находится viewDidAppear , или в методе init / viewDidLoad / viewWillAppear LoadViewController.
Установите несколько точек останова и следуйте до тех пор, пока не произойдет сбой...
У меня возникла аналогичная ошибка при нажатии на UIButton
чтобы открыть Modal View
.Я изменил UIButton's
слушатель из UIControlEventAllEvents
Для UIControlEventTouchUpInside
.По сути, это был запуск модального представления на Touch Down Inside
а затем снова на Touch Up Inside
.
У меня была такая же проблема из-за несоответствия между именами в
HelpViewController *controller = [[HelpViewController alloc] initWithNibName:@"HelpView" bundle:nil];
и имя фактического файла .xib.
Я думаю, что эта проблема как-то связана с проблемой, с которой я также столкнулся.Это очень легко воспроизвести:
Создайте новый проект XCode "Служебное приложение".В FlipsideViewController.m вы просто вставляете следующий метод:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear: animated];
[self showInfo];
}
Если вы сделаете это, запустите приложение, тогда вид с обратной стороны будет активирован сразу же сразу.Как только вы нажмете кнопку "Готово" на обратной стороне экрана, вы вернетесь к главному экрану, который снова запускает viewDidAppear и переходит обратно к обратной стороне экрана- просмотр.Как только отображается вид с обратной стороны, приложение останавливается - нет памяти вызываются средства освобождения - это так же, как если бы вы нажали кнопку "Домой".
Когда я использовал некоторые дополнительные свойства в этих представлениях, я также получал исключение, поэтому я сократил код до минимального объема...
Я действительно понятия не имею, в чем на самом деле заключается эта проблема...
С наилучшими пожеланиями, Тобиас
Это действительно зависит от того, для чего предназначены процедуры поддержки viewDidAppear
делаем.Например, если presentModalViewController:animated:
не сохраняет loader
авария может быть вызвана UIWindowController
пытаясь говорить о loader
который с тех пор был выпущен (в конце опубликованной вами процедуры).
У меня была похожая проблема при использовании той же техники, что и у вас, для реализации загрузочного представления.Это привело бы к сбою, когда загрузочный вид был бы отклонен в конце загрузки.В моем случае проблема возникла из-за того, что, как только представление загрузки было отклонено, viewDidAppear был вызван снова и попытался снова представить представление загрузки, что, предположительно, вызвало сбой.Я исправил это, просто проверив, был ли представлен загрузочный вид ранее:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(needDisplayLoader)
[self presentModalViewController: loader animated:NO];
}
Затем я установил needDisplayLoader в значение NO, прежде чем отклонить представление Loader
Надеюсь, это поможет...
Я столкнулся с этой проблемой только сейчас и исправил ее, используя предложение selector: afterDelay выше.Просто чтобы добавить, я скомпилировал (без исправления) под iPhone OS 4.0 beta, и НИКАКОГО СБОЯ!Итак, ошибка в XCode, похоже, была исправлена в следующем поколении.Не то чтобы это принесло кому-то из нас какую-то пользу сегодня, но, чтобы вы все знали, это действительно был ошибка в Xcode и не обязательно что-то, что мы делали неправильно в наших стилях кодирования.
Была точно такая же проблема.Решил это с помощью предложенного выше...
[self performSelector:@selector(doit) withObject:nil afterDelay:0.5];
Пришлось использовать задержку в 0,5 секунды.Возможно, потому, что я выполнял presentModalViewController непосредственно после модального UIPickerViewController.
У меня только что была эта проблема, и оказалось, что моя проблема заключалась в том, что я освободил своего делегата протокола.
Я думаю, причина цикла заключается в том, что новый загружаемый вами контроллер представления по умолчанию имеет метод viewDidAppear, и он имеет
[super viewDidAppear animated];
это означает, что он снова вызовет viewDidAppear вашего основного контроллера представления, например, что он перейдет в цикл
в Viewcontroller, который вы представляете, есть подобный метод, без super viewdidapper:
-(void)viewDidAppear:(BOOL)animated{
//[super viewDidAppear:animated]; no super
}
EXC_BAD_ACCESS
это ошибка памяти.Вероятно, вы пытаетесь использовать объект, который уже был освобожден.Этот ответ дает несколько советов по отладке этих проблем: