iOS - Weird navigation problem? - ios

I have 3 UIViewControllers in my UINavigationController.
At some points I want to go to rootViewController and from there navigate to a new UIViewController, and it doesn't aeem to work.
Any suggestions?
- (IBAction)goToRootAndNavigateToViewController
{
[self.navigationController popToRootViewControllerAnimated:YES];
MyViewController *mvc = [[MyViewController alloc] init];
[self.navigationController pushViewController:mvc animated:YES];
[mvc release];
//This takes me to the rootViewController but it doesn't navigate to MyViewController
}
Trying to use performSelector:WithDelay:
- (void)goToRootAndNavigateToViewController
{
[self.navigationController popToRootViewControllerAnimated:YES];
[self performSelector:#selector(doSomething) withObject:nil afterDelay:10];
}
- (void)doSomething
{
MyViewController *mvc = [[MyViewController alloc] init];
[self.navigationController pushViewController:mvc animated:YES];
[mvc release];
}

I believe the popToRootViewController takes up the full NSRunLoop.
You would need to push your next view controller with a separate function using something like performSelector:withObject:afterDelay.
or you could always just do a [self.navigationController setViewControllers:] call to set them manually

You need to push your mvc controller when the animation is complete. Try calling it once the first animation is done (e.g. in - (void)viewDidAppear:(BOOL)animated)

I don't know why you are facing this problem, but one solution you could try is to push the new view controller in your root view controller's -viewDidAppear: method.

I guess it has to do with your current viewcontroller using - (IBAction)goToRootAndNavigateToViewController, is somehow losing its control once being popped. Thus, making consecutive statements to be not working.
If I were you, I would make sure pushing MyViewController instance is done always at rootViewController of your choice, not from the current viewcontroller which is going to be popped from UINavigationController and possibly to be released and deallocated.
Probably, you may want to add delegate method implementation for, such as - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated in your rootViewController
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
// Check the right condition for pushing MyViewController...
// if it's YES...
MyViewController *mvc = [[MyViewController alloc] init];
[self.navigationController pushViewController:mvc animated:YES];
[mvc release];
}
In this implementation, you may push MyViewController instance. One thing you have to do beforehand is using some kind of conditional flag, which will make sure the situation is correct for popToRootViewController then push MyViewController

Related

UINavigationController no animations anymore

I have a very weird problem with the UINavigationController on iOS 8, maybe someone encountered this already and can shed some light. I have 2 views: let's say view A and view B
I am using it like this:
view A [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
return to view A [self.navigationController popToRootViewControllerAnimated:YES];
The problem is that if I play with this for 2 min and go through this like push-push-push-push-pop and again... at some time it stops animating, for either push and pop.
I checked the 1) view controllers they get deallocated on the pop to root, 2) I don't receive any memory warnings, 3) the navigation controller is the rootviewcontroller of the window so why this problem?
I can't find any explanation maybe someone has encountered this already. Also I am mentioning I am not using custom animations, just the plain native push and pop of a normal UIViewController, not even subclassing that so everything is plain native.
#kokos8998 try using
#interface AnimatorPushGalleryToGallery : NSObject <UIViewControllerAnimatedTransitioning>
and then in view A just add this and will control everything from view B either A->B or B->A (or in case you need something more custom add the same delegate in B as well)
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.navigationController.delegate = self;
}
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
if(operation == UINavigationControllerOperationPush)
return [AnimatorPushGalleryToGallery new];
else if(operation == UINavigationControllerOperationPop)
return [AnimatorPopGalleryToGallery new];
return nil;
}

Hide and Unhide masterView from button press of detailView

I know this question has asked by many users,But i did not found any answer related to my issue.
I'm using UISplitViewController ,my application starts with login page, so i have hidden masterView on start, after some time on DetailViewController i shown the master viewController using Delegate method.
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation NS_AVAILABLE_IOS(5_0)
{
return hideMaster;
}
i have initialised hideMaster to NO ,and my ViewDidLoad() of DetailViewController is below
ViewDidLoad(){
[self.splitViewController.view setNeedsLayout];
self.splitViewController.delegate =Nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
[super viewDidLoad];
}
it worked fine my master is now unhide.But on the same detailViewController i have a Back Button on which i'm poping the current ViewController to last viewController and again i want to hide masterViewController my code for back button is below.
- (IBAction)back:(id)sender {
hideMaster = NO;
self.splitViewController.delegate =Nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
[self.navigationController popViewControllerAnimated:NO];
}
Its poping the CurrentViewController to last ViewController but its not Hiding the masterViewController
Please help me out.
#JohnD,I went through your code.you are hiding the master view controller while poping the last View controller,but the viewController to which you are navigating is still showing the master View controller.therefore your masterView is still there.
follow the steps given below.
1.make delegate of UInavigationController to that ViewController which is your last singleView controller.
2.In last single ViewController(which is delegate of UINavigationController) implement following delegate method.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self.splitViewController.view setNeedsLayout];
self.splitViewController.delegate =Nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
}
3.Now implement delegate method of UISplitViewController in side lastViewController which is given below.
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation NS_AVAILABLE_IOS(5_0)
{
return hideMaster;<<===============I'm assuming hide master as a variable of shared object(Singleton).
}
4.Now change your - (IBAction)back:(id)sender method with following one.
- (IBAction)back:(id)sender {
hideMaster = Yes;
[self.navigationController popViewControllerAnimated:NO];
}
I hope this will work,if you stuck some where please let me know.
you are using UISplitViewController inside your app,since you have many views but whole app is not using UISplitViewController only one view using it.
Its better to use another approach.

Showing UINavigationController in a Modal segue (ViewController)?

I have now been stuck on this problem for more then 2 weeks! In my project, I have 1 single ViewController(slide) I want to enable both landscape and portrait in. The rest of all controllers/views(slides) I want to enable portrait-mode only.
The tricky part is, the "ViewController" I am referring to is connected to both NavigationControllers and TabBarControllers. See the scheme below where the ViewController I want to enable both landscape/portrait is named: ReferredViewController.
TabBarController ----> NavigationController ----> FristViewController --(push event)--> ReferredViewController
So far I have tried to make a CATEGORY for both NavigationControllers and TabBarControllers. But since my NavigationControllers and TabBarControllers are placed at the very start of the project this will set the rules for the whole project. My ReferredViewController is placed at the end or in the middle of the projects "storyboard". I have tried to set the rules by code aswell for the single ReferredViewController without any success.
My best shot is to change the event between FirstViewController and ReferredViewController from "push" to "modal". ReferredViewController can then rotate both portrait/landscape and the rest of the project is locked in portrait. BUT, as you may know all navigations (NavigationBar) will be lost and the user will become stuck at that single slide.
So I am trying to enable the NavigationBar with the following code example in the ReferredViewController.m file:
ShowTaskViewController *detailViewController = [[ShowTaskViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
navController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentModalViewController:navController animated:YES completion:nil];
[navController release];
[detailViewController release];
But ofc nothing happens and I am back to square one again :O. FML!
In this line:
[self.navigationController presentModalViewController:navController
animated:YES
completion:nil];
you are conflating two UIViewController instance methods:
- (void)presentViewController:(UIViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(void (^)(void))completion
- (void)presentModalViewController:(UIViewController *)modalViewController
animated:(BOOL)animated
The first of these is now the standard, the second method was deprecated in ios6.
Also the presenting view controller should be self (the ReferredViewController), not self's navigationController.
Your presented view controller can dismiss itself thus
[[self presentingViewController] dismissViewControllerAnimated:YES
completion:(void (^)(void))completion];
But take a look at fibnochi's answer, it may be a better way for you to achieve your result.
you have to over ride UITaBarController because it is you base view controller. I have done this for my navigation controller. Tell me if this helped.
#interface UINavigationController (Autorotation)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
- (BOOL) shouldAutorotate;
- (NSUInteger) supportedInterfaceOrientations;
#end
#implementation UINavigationController (Autorotation)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
if ([self.visibleViewController isKindOfClass:[MWPhotoBrowser class]] || [self.visibleViewController isKindOfClass:[ZoomPictureViewController class]]) {
return YES;
}
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL) shouldAutorotate{
return YES;
}
-(NSUInteger) supportedInterfaceOrientations{
if ([self.visibleViewController isKindOfClass:[MWPhotoBrowser class]] || [self.visibleViewController isKindOfClass:[ZoomPictureViewController class]]) {
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}

Receive a ViewDidUnload message through UINavigationControllerDelegate

DetailViewController <-> MasterViewController <-> ViewController
At the moment I solve my problem by having a variable in the ViewController class point to the DetailViewController so that I can perform a method when the DONE button in ViewController is pressed.
- (void)doneButtonPressed {
[self.detailViewController method];
}
What I want to do is to have the ViewController report to DetailViewController when it unloads, so that DetailViewController can perform the method itself.
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[self.navigationController delegate] performSelector:#selector(method)];
}
What I have tried is to have the MasterViewController set the ViewControllers delegate to DetailViewController with this code, when it is pushed:
ViewController *ViewController = [[ViewController alloc] init];
ViewController.navigationController.delegate = self.detailViewController;
[self.navigationController pushViewController:ViewController animated:YES];
UINavigationControllerDelegate has been set in DetailViewController.
What am I doing wrong?
My question was badly formulated.
The answer is in the documentation:
View Controller Programming Guide for iOS
-> Modal View Controllers
Dismissing a Modal View Controller
http://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html#//apple_ref/doc/uid/TP40007457-CH111-SW14

Calling popToRootViewControllerAnimated after dismissModalViewControllerAnimated

I am working application in which i calling presentModalViewController and once finished(calling dismissModalViewControllerAnimated:YES) it should immediately call popToRootViewControllerAnimated.
But the issue is dismissModalViewControllerAnimated:YES is working properly but popToRootViewControllerAnimatedis not working after it.
The code is shown below:
[self.navigationController dismissModalViewControllerAnimated:YES] ;
[self.navigationController popToRootViewControllerAnimated:YES];
Try something like this:
[self.navigationController dismissModalViewControllerAnimated:YES] ;
[self performSelector:#selector(patchSelector) withObject:nil afterDelay:0.3];
-(void)patchSelector{
[self.navigationController popToRootViewControllerAnimated:YES];
}
It is not so neat but it should work.
UPDATE:
You should use
[self dismissModalViewControllerAnimated:YES];
instead
[self.navigationController dismissModalViewControllerAnimated:YES] ;
The object that is presenting the modal is the view controller, not the navigation controller.
If you have a navigation controller with a stack of UIViewControllers:
[self dismissModalViewControllerAnimated:YES];
[(UINavigationController*)self.parentViewController popToRootViewControllerAnimated:YES];
//UIViewController *vc = [[UIViewController new] autorelease];
//[(UINavigationController*)self.parentViewController pushViewController:vc animated:YES];
Assumes, that view controller in which called modal view controller has navigationController.
I ran into something similar to this. You need to make a copy of your self.navigationcontroller first and also retain yourself, so when you call the second pop, there is still a reference to the NC and you still exist.
// locally store the navigation controller since
// self.navigationController will be nil once we are popped
UINavigationController *navController = self.navigationController;
// retain ourselves so that the controller will still exist once it's popped off
[[self retain] autorelease];
// Pop this controller and replace with another
[navController popViewControllerAnimated:NO];
[navController pushViewController:someViewController animated:NO];
see : How can I pop a view from a UINavigationController and replace it with another in one operation?
I guess, you are not calling the
[self.navigationController popToRootViewControllerAnimated:YES];
in the target modal viewcontroller. check that.

Resources