I've a weird problem... in a tabbar application, in the tabBarController i call:
[myController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
self presentModalViewController:myController animated:YES];
myController get presented and everything work but when i try to dismiss it (from within myController) with:
[[self presentingViewController] dismissModalViewControllerAnimated:YES];
It does the dismiss animation, i can almost see my tabBarController active view when suddenly myController re-appear.
The only way to make it work is using the default transition style:
UIModalTransitionStyleFlipHorizontal
Every other animation, or even trying to dismiss myController without animations cause that problem.
After the dismiss call, viewWillDisappear and viewDidDisappear of myController get called.
viewWillAppear and viewDidAppear of myController DON'T get called when it re-appear.
Calling again the dismiss function does nothing.
I'm almost sure nothing is presenting myController again, it's like it's simply not going away completely.
I've tried replacing myController with a fresh new controller with and empty view, nothing changed.
It's sounds like a stupid problem but i really can't understand it...
PS: I'm using iOS5, storyboard, ARC, it's an iphone app, i'm using the simulator (can't try on an iphone at the moment)
Is that dismiss being called from within the modally presented VC? Try this:
[self dismissModalViewControllerAnimated:YES];
Related
I am trying to convert my App to a Storyboard, but am having some problems.
In de previous model I could have an 'actionClass' in my AppDelegate which I called when I needed to pop-up a view.
E.g.
DOArticleViewController *articleView = [[DOArticleViewController alloc] initWithArticle:article notification: notification nibName:#"DOArticleViewController" bundle:nil];
[[self navigationController] pushViewController:articleView animated:YES];
But now with the storyboard it does not work anymore.
Then I tried the following code in the AppDelegate:
id currentController = [[[[self window] rootViewController] navigationController] visibleViewController];
[currentController performSegueWithIdentifier:#"settingsSeque" sender:nil];
Don;t think this is the best anyway, as only the rootViewController has all the seques needed, and might not be the visibleViewController, but one step at a time.
With this the only thing I see happening is the message and no action:
Unbalanced calls to begin/end appearance transitions for UINavigationController: 0xb428e00.
I spend a view hours now on trying to figure out to get this to work, but am realising that it might be better to go back to the traditional independent XIB files....
I solved with the answer given in this question: ios: Accessing a navigation controller from app delegate
I tried to get the Navigation Controller, but this was nil and I didn't realise it.
My navigation controller was the rootViewController, so that is also the NavigationController.
Casting the rootViewController to NavigationController and invoking 'visibleViewController' worked fine after that!
My app has two windows, mainWindow (for almost all views) and loginWindow (just for login view).
When applicationDidEnterBackground I switch mainWindow with loginWindow:
[self.loginWindow makeKeyAndVisible];
[self.mainWindow setHidden:YES];
When I came back in app the loginWindow with its views is shown. That works just fine.
However I have a problem with modalView presentation in mainWindow.
After applicationDidEnterBackground windows are switched again. After going back to mainWindow the modalView is not visible.
Method self.modalViewController gives me the exact modalView that was presented earlier, but is not visible anymore.
I've tried to show this modalView again with no luck like this:
[self presentModalViewController:self.modalViewController animated:NO];
How can I "re-present" this hidden modalView again?
Probably you need some logic here. Like Crio stated, dismiss it when entering the background, but remember it in a property or smth. else.
// applicationDidEnterBackground
self.savedModalViewController = self.modalViewController;
[self.mainWindow dismissModalViewControllerAnimated:NO];
// after login but before presenting the mainWindow again
[self.mainWindow presentModalViewController:self.savedModalViewController animated:NO];
If your showing the "modalView" modally, then on applicationDidEnterBackground dismiss the modal view:
[self.mainWindow dismissModalViewControllerAnimated:NO];
and then the modal should work fine.
I am on a viewController called vcA and I do this:
[self.navigationController pushViewController:vcB animated:YES];
and it works. vcB is pushed. Inside vcB's viewDidAppear I do this:
NSArray *controllers = self.navigationController.viewControllers;
and controllers contains just one object, vcA !!!! (what?)
Why is vcB being added to the controllers array? Is there anything that can prevent that from happening?
thanks.
I banged my head on the wall for a week to solve this problem involving pushing a view controller on the navigation controller stack.
The problem was this: I was on a navigation controlled based app and I had 3 view controllers, vA, vB and vC.
I was pushing vB from vA using this:
[self.navigationController pushViewController:vB animated:YES];
it worked, but, when I tried to push vC from vB, the self.navigationController property of vB was nil and vB was not on the navigation controller stack. What? Yes, I pushed vB on the navigation stack and vB was not being added to it, but even so, vB was showing correctly.
I discovered that inside vB's viewDidLoad, self.navigationController was not nil and that vB was on the navigation controller stack, but as soon as vB's viewDidLoad ended, vB was removed from the navigation controller stack and its navigationController property was set to nil. At that time, vB was a kind of ghost control, outside the navigation controller stack.
I don't need to mention that from vB I was unable to get back to vA or to push vC.
How that happen?
simple, I was pushing vB from inside a block... something like:
void (^ block1)() = ^(){
[self.navigationController pushViewController:vB animated:YES];
};
What was happening because a UIKit function (the push thing) was being executed in a block that was probably running on a thread that was not the main thread.
The resolution to that was to wrap the push in a dispatch to the main thread, using this:
void (^ block1)() = ^(){
dispatch_async(dispatch_get_main_queue(),
^{
[self.navigationController pushViewController:vB animated:YES];
});
};
The app had another minor problem with a wrong outlet connected to a viewController, but this was the main problem. This is the kind of problem hard to spot, for being subtle. I discovered the problem when I added another button to the navigation bar and that button did not appear. So, I suspect that something involving UIKit was happening, or not happening in that case. The big problem here is that this code was not crashing, no error message, nothing, just working bad, but working.
I believe this has to do with the timing of your checking. During the pushViewController method, the next view controller's viewWillAppear: method (and others, such as the one you're checking) are in the process of getting called. I believe after all those method are called, the view controller is considered on the navigation stack AFTER the animation is done completing.
I am facing a crash on iOS 6.0. I have a view controller from which I present a navigation view controller modally and then from the navigation stack I present another view controller modally and finally to dismiss the whole modal stack I pass the following message to my first view controller from where I showed the navigation controller.
Now this works fine on iOS below 6.0. How should I handle this?
[self dismissModalViewControllerAnimated:YES];
I had this similar crash as well and one of the things helped me solve it was adding:
vc.modalPresentationStyle = UIModalPresentationCurrentContext;
maybe because dismissModalViewController is deprecated in iOS6? Try
[self dismissViewControllerAnimated:YES completion:nil];
EDIT: Lets say you add a method to appDelegate called 'makeMeNumberOne:(UIViewController *)vc':
(I know you use the 'modal' versions, they are deprecated in iOS6, switch to 'presented' variants)
. Also I assume you can find the navigationController, if this is a problem add a comment I'll further expand this, and assume you are using ARC.)
the parameter you have is a strong reference, it holds the current presented viewController, lets call it pvc
ask the navigationController for its viewControllers, and get the last one
as a debugging tool, verify that this vc has a non-nil presentedViewController property
message the last view controller above:
[lastOne dismissViewControllerAnimated:NO completion:^{
[navigationController.viewControllers = #[pvc];
}];
I have a UIViewController (call it NumberTwo) which I presented as a modal view controller from another UIViewController (call it NumberOne). NumberTwo contains a touchesBegan method which listens for touches, and it also has an accelerometer method which listens for device orientation changes in the x, y, or z direction. NumberTwo has a button called "Done" which, when tapped, dismisses itself as a modal view controller:
[self dismissModalViewControllerAnimated:NO];
But it seems as though it's still listening for touches, and it's still listening for accelerations. How can I completely free up NumberTwo when I dismiss it? I tried adding a release call as follows:
[self dismissModalViewControllerAnimated:NO];
[self release];
but that caused a EXEC_BAD_ACCESS.
Did you release the controller after you presented it? E.g. in your method in NumberOneController that presents it, do you have something like:
NumberTwoController * controller = [NumberTwoController alloc] init];
// do stuff to config controller
[self presentModalViewController: controller];
[controller release];
Unless you want to hang on to NumberTwoController for re-use, this would be the usual pattern. The presentModalViewController method ensures that the controller is retained while it's in use. It should then get tidied up when, within NumberTwoController, you call [self dismissModalViewControllerAnimated: NO].
I had a very similar issue that plagued me for days. It turned out that my view controller class wasn't being deallocated when I dismissed it because that view controller had an active NSTimer that wasn't being invalidated (stopped). I was able to kill the timer in viewDidDisappear.
Make sure you are releasing everything you use when you finish with it; The dealloc method is only called when the UIViewController and all of its properties/objects are no longer in use. Never use [self release]; you need to release it from the view controller that created it after you are finished with it.