在父视图控制器中管理几个UIViewControllers

时间:2014-03-12 18:28:33

标签: ios uiviewcontroller

我的UIViewController包含另外两个UIViewControllers作为属性。

MenuViewController包含:

@property (nonatomic, strong) TeamsViewController *teamsViewController; 
@property (nonatomic, strong) ResultsViewController *resultsViewController;

MenuViewController包含表格视图,当用户点击单元格“show teams”时,我需要初始化teamsViewController并显示teamsViewController视图。当用户按下单元格“显示结果”时,同样的事情,但在这种情况下,我需要显示resultsViewController视图。

所以,我通常这样做是以单向方式在按下单元格时初始化控制器并调用addSubview方法来添加控制器视图。但我认为这不是一个好的解决方案我是对的吗?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (_teamsViewController) _teamsViewController = nil;
    _teamsViewController = [TeamsViewController new]
    [self.view addSubView:_teamsViewController];

}

上面的方法可以吗?

我的视图层次结构中的每一个都由它自己的控制器管理。所以由MenuViewController管理的白色和由ResultViewController管理的灰色视图和由TeamsViewController管理的蓝色视图。

正如我之前所说,当我点击菜单视图控制器中的相应单元格时,我需要显示团队或结果。但是每个视图都有另一个视图控制器。或许我对视图控制器范式感到困惑?也许TeamsViewController应该是TeamsView,ResultsViewController应该是ResultsView?因此,两个视图控制器都具有在其控制器中管理的表。所以我不认为它必须是UIView而不是UIViewController。

enter image description here

2 个答案:

答案 0 :(得分:1)

我建议使用故事板并确保拥有"故事板ID"对于他们每个人。这样,根据需要推送各种UIViewController实例变得更容易一些。这是我的典型模式:

UIViewController *vc = [self.storyboard
    instantiateViewControllerWithIdentifier:@"selected identifier"];
[self.navigationController pushViewController:vc animated:YES];

此外,除非您需要在子视图控制器中设置属性,否则无需对其进行属性引用。此外,此答案假定您使用UINavigationController,并将MenuViewController设置为rootViewController。您可以使用Storyboard(简单且可能是首选方式)在IB中进行设置,或者使用以下代码进行设置:

MenuViewController *vc = [[UIViewController alloc] initWithNibName:@"" 
                                                            bundle:nil];
UINavigationController *navVc = [[UINavigationController alloc]
                                  initWithRootViewController:vc];

答案 1 :(得分:1)

我认为最好的办法是将其设置为UINavigationController。 UINavigationController继承自UIViewController,因此您不会以这种方式丢失任何功能。然后你可以像这样设置它:

//MenuViewController.h
@interface MenuViewController : UINavigationController
   @property (nonatomic, strong) TeamsViewController *teamsViewController; 
   @property (nonatomic, strong) ResultsViewController *resultsViewController;
   //Insert other properties and methods....

@end

并且在有人点击某个单元格时调用的方法中,您只需执行此操作:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (!self.teamsViewController) {
       self.teamsViewController = [[UIViewController alloc] initWithNibName:@"nibName" bundle:nil];
    }
    [self pushViewController:self.teamsViewController animated:YES];
}

现在,你有两个视图控制器,所以你必须告诉你的方法上面哪一个推入堆栈。如果行是固定的,您可以根据indexPath简单地决定显示哪一行,但如果它更动态(即从数据库创建tableview),那么您需要在这里使用一些更复杂的逻辑代码。 / p>

没有做太多的假设,但为了给你一些一般的指导,当你创建一个单元格时,你通常会在它上面设置某种标志来指示它是什么类型。如果您只有两个状态,可以使用NS_ENUM或简单的BOOL来完成(我更喜欢尽可能使用ENUM,因为它们更具描述性)。然后,您将在tableView:didSelectRowAtIndexPath:方法中检查该标志是否存在,将相应的视图推送到导航堆栈。这样的事情(这不是文字代码,但只是为了给你一个想法:

// This code assumes in the method tableView:cellForRowAtIndexPath:
// you have set the tag property to '1' if a TeamsViewController is
// needed or '2' if a ResultsViewController is needed when that cell
// is pressed.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        self.teamsViewController = self.teamsViewController ? self.teamsViewController : [[UIViewController alloc] initWithNibName:@"TeamsViewController" bundle:nil];
        self.resultsViewController = self.resultsViewController ? self.resultsViewController : [[UIViewController alloc] initWithNibName:@"ResultsViewController" bundle:nil];
        switch ([[tableView cellForRowAtIndexPath:indexPath] tag]) {
           case 1:
              [self pushViewController:self.teamsViewController animated:YES];
              break;
           case 2:
              [self pushViewController:self.resultsViewController animated:YES];
              break;
           default:
              break;
        }
    }

您仍然需要在团队或结果视图控制器中进行初始化以显示视图,但这应该引导您向大方向发展。