多个调用添加到导航堆栈

时间:2016-10-28 19:39:59

标签: ios objective-c uinavigationcontroller

我有三个标签栏控制器。从那些标签栏控制器,有按钮可以转到不同的视图。其中一些视图是与标签栏视图控制器相同的其他视图控制器,有些则不是。这些不同的视图反过来可以转到其他视图。实际上,用户可以继续以这种方式永久分配新视图。三个主要观点是NewsFeedVC ProfileVC和NotificationsVC。然后,辅助视图包括VotesListVC。预期用途是用户可以选择三个选项卡中的一个并继续在堆栈上弹出更多视图控制器。用户可以一直点击导航后退按钮到原始视图,或点击另一个选项卡。点击其他选项卡应该释放前一个堆栈上的视图控制器堆栈;返回原始选项卡将显示根视图控制器。问题是我的代码已经变得非常难看,试图确定哪个视图控制器是最后一个。在这个应用程序中,我选择退出故事板,所以我必须自己做所有的导航。我的问题是,知道堆栈上的内容以及如何删除它的正确方法是什么。 以下是我正在使用的一些代码。

//for when the user wants to leave an individual post allViewControllers is an array    
 NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray: self.navigationController.viewControllers];

-(void)backTapped{
if (_postKey) {
    ActivityViewController *newVC = [allViewControllers objectAtIndex:1];
    [allViewControllers insertObject:newVC atIndex:0];
    [allViewControllers removeLastObject];
    self.navigationController.viewControllers = allViewControllers;

    CATransition* transition = [CATransition animation];
    transition.duration = 0.2f;
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromLeft;
    [self.navigationController.view.layer addAnimation:transition
                                                forKey:kCATransition];
    [self.navigationController popViewControllerAnimated:NO];
}
}


//Here is how I handle leaving the profileVC, I have booleans determining what view it is from.

-(void)backTapped{

if (fromWorldFeed) {
    WorldFeedViewController *newVC = [allViewControllers objectAtIndex:1];
    newVC.retainTablePosition=true;
    [allViewControllers insertObject:newVC atIndex:0];
    [allViewControllers removeLastObject];
    self.navigationController.viewControllers = allViewControllers;

    [self.navigationController popViewControllerAnimated:NO];
}else if(_fromActivity){
    ActivityViewController *newVC = [allViewControllers objectAtIndex:1];
    [allViewControllers insertObject:newVC atIndex:0];
    [allViewControllers removeLastObject];
    self.navigationController.viewControllers = allViewControllers;
}else{
    VotesListViewController *newVC =[allViewControllers objectAtIndex:1];
    [allViewControllers insertObject:newVC atIndex:0];
    [allViewControllers removeLastObject];
    self.navigationController.viewControllers =allViewControllers;
}
CATransition* transition = [CATransition animation];
transition.duration = 0.2f;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.navigationController.view.layer addAnimation:transition
                                            forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];
}

我在加载时保存标签栏索引,以便知道它是否发生变化,然后我可以以某种方式释放旧标签视图堆栈。

-(void)setTabBarIndex{
NSInteger tabBarIndex =self.tabBarController.selectedIndex;
NSString *tabBarStr=[@(tabBarIndex) stringValue];
[[NSUserDefaults standardUserDefaults]setObject:tabBarStr forKey:@"tabBarIndex"];

}

如果用户最多只能导航到一个或两个视图,那么此代码就可以了。但是,当用户深入到应用程序时,我遇到了很难解决的问题。 我可以通过某种方式让我的应用代表管理这个吗?

1 个答案:

答案 0 :(得分:1)

正如您所提到的,UITabBarController中有三个选项卡。所以先拿三个UINavigationController。 NewsFeedVC,ProfileVC和NotificationsVC将成为这三个UINavigationControllers的rootViewController。

newsFeedNavigationController = [[UINavigationController alloc] initWithRootViewController:yourNewsFeedVCObject];
profileNavigationController = [[UINavigationController alloc] initWithRootViewController:yourProfileVCObject];
notificationsNavigationController = [[UINavigationController alloc] initWithRootViewController:yourNotificationsVCObject];

yourTabBarController.viewControllers = @[newsFeedNavigationController, profileNavigationController, notificationsNavigationController];

现在,如果你想显示任何新视图控制器只需按下视图控制器,相应的导航控制器就会处理堆栈。

假设您选择了新闻提要标签,那么当前的导航控制器就是newsFeedNavigationController。现在,您要将视图控制器A推送到该控制器上。只需在该导航控制器上按下视图控制器A的对象即可。如果要在该导航控制器上推送ProfileVC或NotificationVC对象,请执行此操作,您无需切换/更新yourTabBarController.selectedIndex值。因为您已经在newsFeedNavigationController上推送了ProfileVC或NotificationVC的对象,并且您仍然在该导航控制器上。这是iOS应用程序的正常行为。

查看控制器的newsFeedNavigationController,profileNavigationController和notificationsNavigationController的堆栈将会有所不同。推送/弹出将根据需要在导航控制器上执行(想要显示视图控制器 - 推,想要回弹)。你不必混合它们。