9

I can't find any logical explanation, but the fact remains that, in iOS 5 (xCode 4.2), if I presentModalView:* animated:YES, I can call dismissModalViewAnimated:* fine, but if I call presentModalView:* animated:NO, then calling the dismiss method crashes. (This works the same if I use the new presentViewController:animated:completion: + dismissViewControllerAnimated:). I am going TRY to work around this for now (I don't want the presentation animated) and report a bug to Apple, but I have been beating my head on this for a while. Any and all suggestions are welcome. Not much out there on iOS 5, so please help if you can. Sample code that does not crash in iOS 4 or iOS 5:

LoginController *loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
[self presentModalViewController:loginController animated:YES];
[loginController release];
...
[self dismissModalViewControllerAnimated:YES];

This will crash in iOS 5 with EXC_BAD_ACCESS on the dismiss call:

LoginController *loginController = [[LoginController alloc]    initWithNibName:@"LoginControllerGG" bundle:nil];
[self presentModalViewController:loginController animated:NO];
[loginController release];
...
[self dismissModalViewControllerAnimated:YES]; //crashes with EXC_BAD _ACCESS

One note: I have an animation within the loginController that happens on viewDidLoad. Going to see if taking that out changes anything, but I wanted to get this out there since I need a solution asap.


[Edit] Full code flow... In AppDelegate, application:didFinishLaunchingWithOptions:

if (!loggedIn)  [myViewController showLoginPanel];

In myViewController:

- (void)showLoginPanel {    
    LoginController *loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
    if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]) {
        [self presentViewController:loginController animated:NO completion:nil];
    } else {
        [self presentModalViewController:loginController animated:NO]; //iOS 4 works fine with or without animation   
    } 
    [loginController release];  
}

In loginController:

- (IBAction)closeLoginWindow {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"CloseLoginWindow" object:nil];
}   //doing it this way because calling on the self.parentViewController doesn't work

Back in myViewController:

- (void) viewDidLoad
    ...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeLoginWindow) name:@"CloseLoginWindow" object:nil];
    ...

- (void)closeLoginWindow {
    if ([self respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) {
        [self dismissViewControllerAnimated:YES completion:nil];    //iOS 5 crashes only if presentation was not animated
    } else [self dismissModalViewControllerAnimated:YES];    //deleting the previous condition, iOS 5 still crashes if presentation was not animated
}    
jbcaveman
  • 911
  • 1
  • 10
  • 19
  • As I suspected, removing the animation from the viewDidLoad method of loginController has no bearing on the issue. Grasping at straws here. – jbcaveman Oct 19 '11 at 12:58
  • That sure is strange. Are you sure you are not releasing loginController at any place other than [loginController release] ? – Manali Oct 19 '11 at 13:02
  • I will check to be sure, but changing the animation flag and leaving all other code as is causes a crash. I would think a management problem would present itself regardless of the animation, but this is inexplicable at the moment, so I will surely check. – jbcaveman Oct 19 '11 at 13:09
  • @Manali, there are other methods that instantiate that class, but none exist at the time of this crash. I will edit my post to show the exact flow. – jbcaveman Oct 19 '11 at 13:16
  • Just put in a NSLog to check for low memory warnings that might be releasing the view, and I have no warnings and no log appears. – jbcaveman Oct 19 '11 at 14:07

2 Answers2

4

In iOS5 the managing of the lifecyle somehow changed and I cannot explain that issue in detail. Anyway, the fix is to postpone that workflow from applicationDidFinishLaunchingWithOptions to applicationDidBecomeActive. It seems that something isn't initialized right at the call of applicationDidFinishLaunchingWithOptions.

- (void)applicationDidFinishLaunchingWithOptions:... {    
    // in order to do this only at launching, but not on every activation 
    // Declaration as property for example
    applicationDidLaunch = YES;
}

- (void) applicationDidBecomeActive:(UIApplication *)application {
    if (applicationDidLaunch) {
        applicationDidLaunch = NO;
        [Start your login Workflow with modal view presenting here]
    }
}

Curious to ur feedback :)....

Rene Berlin
  • 1,171
  • 7
  • 21
  • Looks like I don't have to go through and change all of my presentModalViewController calls to presentViewController calls like I thought. Whew, I can save that for the next release. – jbcaveman Oct 19 '11 at 16:43
  • I had the same problem, just moved it to DidBecomeActive and submitted the fix in order to have a bug-free version in the Store... No idea what lifecycle changes Apple did... – Rene Berlin Oct 19 '11 at 23:43
  • it doesn't help me with : http://stackoverflow.com/questions/11832981/dismissviewcontrolleranimated-crash-at-ios5 –  Aug 07 '12 at 15:49
2

I will add my 2 cents : i had ImagePickerController and got its dismissing working only when i did not release the picker manually (IOS 5 SDK).

So. for your case i could offer such workaround : 1. remove line - [loginController release]; 2. to prevent memory leaks add loginController as a property to your current controller and release it only in dealloc() of current controller :

@interface myViewController : UIViewController 

@property (nonatomic, retain) LoginController *loginController;

@end

...

@implementation myViewController

- (void)showLoginPanel {    
    self.loginController = [[LoginController alloc] initWithNibName:@"LoginControllerGG" bundle:nil];
     // ... something goes here  
}

-(IBAction)loginClose() 
{
    // this should close all windows as far as you call it from current (main) controller
    [self dismissModalViewControllerAnimated:YES]; 
    // ... then anything you want EXCEPT [loginController release];
}

-(void)dealloc() 
{
    [loginController release];
}

@end

Good luck :)

P.S. I have just written this so it is just an idea how to cheat it. Somebosy may correct me ... though anyway it worked for me.

Anonymous
  • 1,823
  • 2
  • 35
  • 74
  • I have the showLoginPanel on (IBAction) and the login close as a callback, but in main thread, also the logincontroller relase in dealloc only and I have the crach : http://stackoverflow.com/questions/11832981/dismissviewcontrolleranimated-crash-at-ios5 –  Aug 07 '12 at 15:54