Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning on two navigation controller which presented as modal

I have created two UIViewControll which is presented as modal. Lets say for first 5 tries, the modal will present normally but afterwards it will give me a :

Warning: Attempt to dismiss from view controller <UINavigationController: 0x76a8450> while a presentation or dismiss is in progress!

Below is the code for dismissing the current view controller and presenting another

[customAlertLoad dismissViewControllerAnimated:NO completion:^{ 
     CustomAlertMsg *cust = [[CustomAlertMsg alloc] init];
     cust.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
     cust.modalPresentationStyle = UIModalPresentationFormSheet;
     cust.delegate = self;

     [self.navigationController presentModalViewController:cust animated:YES];
     cust.view.superview.frame = CGRectMake(0, 0, 458, 230);
     cust.view.superview.center = self.view.center;
}];

Any help will be very much appreciated.

like image 359
Rye Avatar asked Feb 18 '13 09:02

Rye


1 Answers

edit

I just remembered another similar issue from a few weeks ago. You are experiencing a race condition, which can probably be solved using GCD (Grand Central Dispatch). This is similar to the solution @rakeshNS suggested, but less dangerous. (Using timers is bad practice to handle a race condition, although in many languages calling a method with a timer wait of 0 seconds is a trick used to put that method call at the end of the call stack, aka make it asynchronous). Apple provides a mechanism for this.

I would try making this slight edit:

[customAlertLoad dismissViewControllerAnimated:NO completion:^{ 
                             dispatch_async(dispatch_get_main_queue(), ^(void) {
                                  CustomAlertMsg *cust = [[CustomAlertMsg alloc] init];
                                  cust.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
                                  cust.modalPresentationStyle = UIModalPresentationFormSheet;
                                  cust.delegate = self;

                                  [self.navigationController presentModalViewController:cust animated:YES];
                                  cust.view.superview.frame = CGRectMake(0, 0, 458, 230);
                                  cust.view.superview.center = self.view.center;
                                 });
                         }];

The call to dispatch_async puts the block at the end of the execution stack. There is no way for this to run before the modal has been dismissed. This also allows for animation on the dismissal AND presentation of the two modals.

I should however mention that in this particular problem, this is a hack. You have an issue somewhere else. If I reproduce your setup in a test project, I can create/dismiss as many modals as I want from the completion blocks without running into your error (as long as the dismissal code is being called from a custom delegate callback used to dismiss the modal, like apple suggests). I would be looking through your custom alert load and custom alert classes code.

end edit

This may not be the same as your issue, I have experienced this problem before with popovers after moving my code base to ARC. There were weird things happening where my Popover was being released too early, or retained too long. The solution was to create an Instance Variable to hold the Popover, and managed nil'ing it out manually. Then everything started working honkey dory.

So I would do:

@interface YourClass:UIViewController

@property (nonatomic,strong) CustomAlertMsg *cust;

@end


@implementation YourClass

... Codey Code....

-(void)pushView{
     // For the sake of sanity, nil the modal here
     if(self.cust != nil) self.cust = nil;
     self.cust = [[CustomAlertMsg alloc] init];
     self.cust.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
     self.cust.modalPresentationStyle = UIModalPresentationFormSheet;
     self.cust.delegate = self;

     [self.navigationController presentModalViewController:self.cust animated:YES];
     self.cust.view.superview.frame = CGRectMake(0, 0, 458, 230);
     self.cust.view.superview.center = self.view.center;
}

// Then where you dismiss it, or in the delegate callback that is 
//  called when you dismiss it, if you are using one anyway, 
//  nil it out
- (void)methodThatDismissesModal
{
     [self dismissModalViewControllerAnimated:YES];
     // This is pretty important
     if(self.cust != nil) self.cust = nil; 
}

... Codey Code....

@end
like image 88
G. Shearer Avatar answered Sep 21 '22 00:09

G. Shearer