In my project, I was using some code to handle the back button as follows.
NSMutableArray *VCs = [NSMutableArray arrayWithArray: self.navigationController.viewControllers];
if ([[VCs objectAtIndex:[VCs count] - 2] isKindOfClass:[LoginViewController class]])
{
[VCs removeObjectAtIndex:[VCs count] - 2];
[VCs removeObjectAtIndex:[VCs count] - 2];
}
[self.navigationController setViewControllers: VCs];
In iOS 7 I am getting the desired result. But for iOS version 8.2, the value in the mutable array VCs is only the current or topViewController in the stack. But the back button will navigate you to all the previous viewcontrollers. But none of them is present there in the navigation stack.Is there any change in the navigation handling in ios8?
I want to delete the login screen viewcontroller from the stack so that on clicking the back button,it will not go back to the login screen. I am facing this issue in iOS 8.2 only (may in iOS 8 and above). What can be the issue?
Edit:
In the prepareForSegue:, I am using the following code:
if([[segue identifier] isEqualToString:#"mediaDetailSegue1"])
{
MovieDetailViewController *movieDetail;
if(isIOS8SystemVersion)
{
movieDetail = ([[segue destinationViewController]viewControllers][0]);
}
else
{
movieDetail = [segue destinationViewController];
}
movieDetail.videoData = [_mediaContentArray objectAtIndex:selectedIndex];
}
so for iOS versions greater than 8,the code
movieDetail = ([[segue destinationViewController]viewControllers][0]);
is called. I think this is causing the issue. Am I doing it wrong?
I got the reason why my navigation Stack is having only one viewController.
In iOS8 and above,if we make a segue from a viewController to a second viewController through the navigationController of the second VC,then the navigationStack of the second VC will contain only the topViewController.
I tried creating a sample project.If the segue is from the VC to second VC directly,then the navigation stack of VC2 will contain VC1 and VC2.If the segue is through the navigation controller of VC2,then the navigation stack of VC2 will contain VC2 only.Strange behaviour of iOS8.
IN both these cases,the app behaves the similar in ios 7.Dont know why it behaves strange in ios8
I'm trying the same with iOS 8.2. self.navigationController.viewControllers returns all view controllers in stack.There is no such issues.I'm not sure Why you are facing such issue.
Try using this Code.It works fine for me.
NSMutableArray *VCs = [NSMutableArray arrayWithArray: self.navigationController.viewControllers];
for(int i = 0; i < VCs.count; i++)
{
UIViewController *vc = VCs[i];
if ( [vc isKindOfClass:[LoginViewController class]])
{
[VCs removeObjectAtIndex:i];
}
[self.navigationController setViewControllers: VCs];
Related
enter image description here
Image on above link, cant include it in the post..
As I push from viewControllerA to B, then I push from B to C, then I use the following code to remove the viewControllerB and push C to B and remove viewControllerC:
NSMutableArray *navigationArray = [[NSMutableArray alloc] initWithArray: self.navigationController.viewControllers];
for(UIViewController *tempVC in navigationArray)
{
if([tempVC isKindOfClass:[viewControllerB class]])
{
[tempVC removeFromParentViewController];
}
}
[self performSegueWithIdentifier:#"toViewControllerB" sender:self];
for(UIViewController *tempVC in navigationArray)
{
if([tempVC isKindOfClass:[viewControllerC class]])
{
[tempVC removeFromParentViewController];
}
}
So now ViewControllerA is connected to the last ViewControllerB
After that I still get the back button in the navigation bar, but after I pressed the back button of it, the ViewControllerB popped back to ViewControllerA, but in the ViewControllerA, the navigation bar items and title are gone, I purposely push from C to B again to fix some memory issue, how can I make this work by taking out the two view controllers in the middle but not messing up the navigation controller? Is there any other alternatives to get this done? Thank you
I have another weird approach is to programatically create a navigation bar with the same items and title to cover it, but just seems so wrong...
First when you want to push from B to C and then remove B, you can try this
for(UIViewController *tempVC in navigationArray)
{
if([tempVC isKindOfClass:[viewControllerB class]])
{
[navigationArray removeObject:tempVC];
break;
}
}
[self.navigationController setViewControllers:navigationArray];
[self performSegueWithIdentifier:#"toViewControllerB" sender:self];
But you must ensure the segue is from C to B. Then you will get the Controllers A->C->B. If you want to push to ControllerC and remove Last C. Try to use the same function.
1) When you first push to your C controller from B then first Remove B controller
2) When you push to B controller from C controller then remove C controller.
// Code for removing C Controller from stack
NSArray *viewControllers = self.navigationController.viewControllers;
NSMutableArray *viewControllersMutable = [NSMutableArray arrayWithArray:viewControllers];
for (UIViewController *vc in viewControllers) {
if (([viewControllers indexOfObject:vc] != viewControllers.count - 1 ) && [vc isKindOfClass: C.class] ){
NSLog(#"removing contoller of kind C");
[viewControllersMutable removeObject:vc];
}
}
self.navigationController.viewControllers = viewControllersMutable.copy;
// Code for removing B controller
NSArray *viewControllers = self.navigationController.viewControllers;
NSMutableArray *viewControllersMutable = [NSMutableArray arrayWithArray:viewControllers];
for (UIViewController *vc in viewControllers) {
if (([viewControllers indexOfObject:vc] != viewControllers.count - 1 ) && [vc isKindOfClass: B.class] ){
NSLog(#"removing contoller of kind B");
[viewControllersMutable removeObject:vc];
}
}
self.navigationController.viewControllers = viewControllersMutable.copy;
Note -> You can do this in a same code Only "OR" condition is checked, means the controller is B or C.
I'm using the CNContactPickerViewController to access contacts. And everything works fine until the part where I want to use this in Tabbar.
In previous ios versions replacing the view by the picker worked well but in ios 9 does not show anything.
When I use this code to present view the tabbar disappears.
[self presentViewController:my_picker animated:YES completion: nil];
I want have the tabbar always visible and the contacts list inside the tab.
Using ABPeoplePickerNavigationController I replace the view with the following code and it works fine.
picker = [[ABPeoplePickerNavigationController alloc] init];
NSMutableArray *controllers = [NSMutableArray arrayWithArray [self.tabBarController viewControllers]];
int index = [controllers indexOfObject:self];
[controllers replaceObjectAtIndex: index withObject: picker];
Someone has a solution for this using?
Just use these lines into your code ,
my_picker.modalPresentationStyle=UIModalPresentationOverCurrentContext;
[self presentViewController:my_picker animated:YES completion:nil];
Now the tabBar won't disappear from your screen
I have used the following code for deleting my login page from the navigationcontroller(viewcontrollers) so that it will not come into the view again when going back (back button).
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
NSMutableArray *VCs = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
if([[VCs objectAtIndex:[VCs count] - 2] isKindOfClass:[loginViewController class]]&&(VCs.count>=4))
{
[VCs removeObjectAtIndex:[VCs count] - 2];
[VCs removeObjectAtIndex:[VCs count] - 2];
[self.navigationController setViewControllers: VCs];
}
}
This works perfectly for iPhone. But for iPad, since we are using splitViewController, if we code like
NSMutableArray *VCs = [NSMutableArray arrayWithArray:self.splitViewController.viewControllers];
What we will be getting is an array of navigationControllers. Is there a genuine logic by which we can delete a particular viewcontroller from the splitviewcontroller?
Your split view controller, as you said, will return an array of nav controllers (depending on the project setup). Once you have a reference to those, you can manipulate them however you want.
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *masterNavVC = (UINavigationController *)splitViewController.viewControllers.firstObject;
UINavigationController *detailNavVC = (UINavigationController *)splitViewController.viewControllers.lastObject;
//Now you have the master and detail navigation controllers, get your VC you need to manipulate
NSMutableArray *masterVCs = masterNavVC.viewControllers;
NSMutableArray *detailVCs = detailNavVC.viewControllers;
//Remove the ones you need to - this example is arbitrary. Put your logic here
if(masterVCs.count > 0 && [masterVCs[0] isKindOfClass:[LoginViewController class]])
{
//Remove or add
}
After pushing a ViewController using this code
UIViewController *vc = [[self storyboard] instantiateViewControllerWithIdentifier:#"frontCardViewController"];
[self.navigationController pushViewController:vc animated:YES];
I remove all ViewControllers I don't need anymore using this code
NSMutableArray *navigationArray = [[NSMutableArray alloc] initWithArray:self.navigationController.viewControllers];
NSArray *array = [[NSArray alloc] initWithArray:navigationArray];
for (UIViewController *viewController in array) {
if ([viewController isKindOfClass:[RITCardViewController class]]) {
RSLog(#"Is kind of Class RITCardViewController");
[navigationArray removeObject:viewController];
}
}
self.navigationController.viewControllers = navigationArray;
The navigation array now looks like this:
"RITMainViewController: 0x10d81fc1>",
"RITDetailViewController: 0x10d847880",
"RITTestResultViewController: 0x113d0e090"
But the problem is that if the back button in the navigation bar is pressed now, it goes back to the second screen. But when the back button is pressed again it just stays on this screen. It seems to go trough all the screens I have removed, but doesn't show them.
What am I doing wrong?
Try something like this instead:
NSMutableArray *viewControllers = [#[] mutableCopy];
for (UIViewController *vc in self.nagivationController.viewControllers)
{
if (NO == [vc isKindOfClass:[RITCardViewController class]])
[viewControllers addObject:vc];
}
self.navigationController.viewControllers = viewControllers;
Make sure you don't corrupt the stack by removing the view controller you are currently on from the view controllers array. Assuming your current view controller is not an instance of RITCardViewController you should be fine. Otherwise, you'll have to make up for it in your code.
I have a UITabBarController which containing 4 different UIViewControllers.
On first tab there is a UINavigationViewController which contains its child UIViewController. without tapping the tab bar, i want to take user on second tab. For this I tried:
self.navigationController.tabBarController.selectedIndex = 1;
But it's not working.
ignore any mistake i am a newbie.
Thank you.
if set delegate
Try this:
self.selectedIndex = 1;
You are the tabBarController :)
Do the following, before trying to change tab:
UITabBarController *tab = self.tabBarController;
if (tab) {
NSLog(#"I have a tab bar");
[self.tabBarController setSelectedIndex: 1];
}
else {
NSLog(#"I don't have one");
}
Try moving your tab switch code to viewDidLoad
I verified that this works on the built in Tabbed Application template project in xcode 4
- (void)viewDidLoad
{
[super viewDidLoad];
self.tabBarController.selectedIndex = 1;
}
I'd also take a look at your AppDelegate class for something along the lines of this
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
If you don't see these lines anywhere then you'll want to find where else in your code the UITabBarViewController is being initialized and use that object pointer instead.
for calling the tabbarcontroller.selectedindexyou must have to find out the tabbarcontroller from the navigation controller if you dont use push on navigationController just use topViewController property of navigationController to get the instance of your tabBarController and assign it to UITabBarController and us the selectedIndex and this will work fine
just try
self.tabBarController.selectedIndex = 1
we should put follow section in viewDidAppear.
- (void)viewDidAppear:(BOOL)animated
{
NSArray *ary = [self.tabBarController viewControllers];
UIViewController *vc = ary[3];
[self.tabBarController setSelectedIndex:3];
[self.tabBarController setSelectedViewController:vc];
}
If you are presenting a new controller (different from the one that's currently on screen) you should set the index in the completion block of the function to present your view controller. If you set it before it's presented, it may not work.
In my case I've embedded the tab controller inside a nav controller. I present the new nav controller newNavContoller, and once it's presented I set the index in my tab controller tvc:
currentViewController?.presentViewController(newNavController, animated: true, completion: {tvc.selectedIndex = selectedIndex})