I'm trying to display a modal view straight after another view has been presented modally (the second is a loading view that appears).
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Show load
LoadViewController *loader = [[LoadViewController alloc] init];
[self presentModalViewController: loader animated:NO];
[loader release];
}
But when I do this I get a "Program received signal: "EXC_BAD_ACCESS"." error.
The stack trace is:
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
Any ideas? I'm totally stumped! The loading view is empty so there's definitely nothing going on in there that's causing the error. Is it something to do with launching 2 views modally in the same event loop or something?
Thanks,
Mike
Edit: Very strange... I have modified it slightly so that the loading view is shown after a tiny delay, and this works fine! So it appears to be something within the same event loop!
- (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];
}
I have modified it slightly so that the loading view is shown after a tiny delay, and this works fine! So it appears to be something within the same event loop!
- (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];
}
I believe I reproduced the same error in iOS 4. In my application, the crash occurred consistently when attempting to show a second modal view immediately after showing a first modal view. I struggled for a few hours going insane.
After reading the posts in this thread, I tried to create a simple reproducible example using the Tab Bar Application template. I was able to use the UIImagePickerController to show the first modal view after responding to a button click in "FirstViewController.m". When I tried to show the UIImagePickerController again (after handling the imagePickerControllerDidCancel message), the application crashed with the same error.
On the device, there was simply no clue what was going on. However, when I ran the code on the Simulator, I was lucky enough to get this message on the console:
*** 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'
So it seems that my only choice is to follow the advice of the error message and simply wait until viewDidAppear (using a flag to indicate I'm in this special mode) and then load the second modal view.
Here's the full stack trace for completeness:
** 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
Hope this helps.
**Like was said earlier, use 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];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With