IOS missed ModalViewController EXC_BAD_ACCESS results

Calling the rejectModalViewController function will break with EXC_BAD_ACCES.

Intermittency is assembly specific, not run specific. That is, if the executable was compiled, the call will either pass sequentially or fail sequentially.

This seems to be independent of whether the code has changed between assemblies.

We are using the iPhone 5.1 and iPod touch 4th generation simulator with iOS 5.1 installed. This behavior is present in both simulated and physical devices.

Has anyone seen this before? We're out of our mind.

Here and where the modal view controller is displayed, as well as where it deprecates:

PaymentStack* paymentStack = 
[[PaymentStack alloc] initWithOrder:[anOrderManager thisOrder] locationState:[appData locationState]
                           //Push the current order on the history list
                           [[appData ordersHistory] addObject:[anOrderManager thisOrder]];
                           if ([[anOrderManager thisOrder] isEffectivelyEqual:[anOrderManager thisOrder]])
                               //Allocate a new order
                               [anOrderManager setOrder:[[Order alloc] init]];

                        [self dismissViewControllerAnimated:YES 
                      [self dismissViewControllerAnimated:YES 
[self presentModalViewController:[paymentStack navigationController] animated:YES];


Here's the stack trace:

#0  0x00d659ab in -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] ()
#1  0x00b4ea9c in -[UIViewController _dismissViewControllerWithTransition:from:completion:] ()
#2  0x00b4df91 in -[UIViewController dismissViewControllerWithTransition:completion:] ()
#3  0x00b4ec81 in -[UIViewController dismissViewControllerAnimated:completion:] ()
#4  0x00071135 in __35-[MasterViewController placeOrder:]_block_invoke_0186 at /Users/jake/Documents/Avocado/AvocadoTest1.0/MasterViewController.m:258
#5  0x000515c0 in __91-[PaymentStack initWithOrder:locationState:successBlock:completionBlock:cancellationBlock:]_block_invoke_0 ()
#6  0x000545c8 in __27-[PaymentStack showSuccess]_block_invoke_0230 ()
#7  0x000558cc in -[PaymentCompleteViewController done] ()
#8  0x01a47e99 in -[NSObject performSelector:withObject:withObject:] ()
#9  0x00a8214e in -[UIApplication sendAction:to:from:forEvent:] ()
#10 0x00cc0a0e in -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] ()
#11 0x01a47e99 in -[NSObject performSelector:withObject:withObject:] ()
#12 0x00a8214e in -[UIApplication sendAction:to:from:forEvent:] ()
#13 0x00a820e6 in -[UIApplication sendAction:toTarget:fromSender:forEvent:] ()
#14 0x00b28ade in -[UIControl sendAction:to:forEvent:] ()
#15 0x00b28fa7 in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#16 0x00b28266 in -[UIControl touchesEnded:withEvent:] ()
#17 0x00aa73c0 in -[UIWindow _sendTouchesForEvent:] ()
#18 0x00aa75e6 in -[UIWindow sendEvent:] ()
#19 0x00a8ddc4 in -[UIApplication sendEvent:] ()
#20 0x00a81634 in _UIApplicationHandleEvent ()
#21 0x03dd9ef5 in PurpleEventCallback ()
#23 0x0197eff2 in __CFRunLoopDoSource1 ()
#24 0x0197d8da in __CFRunLoopRun ()
#25 0x0197cd84 in CFRunLoopRunSpecific ()
#26 0x0197cc9b in CFRunLoopRunInMode ()
#27 0x03dd87d8 in GSEventRunModal ()
#28 0x03dd888a in GSEventRun ()
#29 0x00a7f626 in UIApplicationMain ()
#30 0x000025ed in main at /Users/jake/Documents/Avocado/AvocadoTest1.0/AvocadoTest1/main.m:16


If there is a better way I can format it for you, let me know.


source to share

3 answers

When you run something like:

[self dismissViewControllerAnimated:YES 


inside the block and do something like:

[self presentModalViewController:[paymentStack navigationController] animated:YES];


outside of the block, it is impossible to know which line of code will work first. Sometimes it will be rejectViewControllerAnimated: otherwise it will be currentModalViewController :.

If the rejectViewControllerAnimated: function is fired first, then the viewController probably gets dealloc'ed, so when the app tries to start the presentModalViewController: it sends a message to an object that no longer exists and is likely causing the crash.

Good luck!



The problem I ran into (with the same symptoms like this) turned out to be (after a solid day of debugging!) The following situation:

1) View controller A presents (using currentViewController: animated: completion :) view controller B.

2) View controller B keeps a weak reference to view controller A (delegate reference).

3) View controller B executes a method of view controller A, which releases view controller A as a side effect.

4) Controller B tries to reject itself using:

[self dismissViewControllerAnimated:NO completion:completion];


Part of the difficulty in tracking this process comes from step 3) being asynchronous. Step 4) and step 3) is not finished yet. Ie, view controller B was released partially through step 4).



Try to store 2 strong pointers: one for the PaymentStack viewController and one for "self". This will help determine who was destroyed. Add "- (void) dealloc" methods for each viewControllers and add breakpoints to those methods. This will help locate the point of destruction.



All Articles