【问题标题】:Manage few UIViewControllers in parent view controller在父视图控制器中管理几个 UIViewController
【发布时间】:2014-03-12 18:28:32
【问题描述】:

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

MenuViewController 包含:

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

MenuViewController 包含表格视图,当用户点击“显示团队”单元格时,我需要初始化teamViewController 并显示teamViewController 视图。当用户按下单元格“显示结果”时也是如此,但在这种情况下,我需要显示 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。

【问题讨论】:

  • 使用 uinavigationcontroller 作为 MenuViewController 的基类并将其他视图控制器推送到导航堆栈可能更容易。这也将为您提供内置的“返回”功能。
  • @MySpecialPurpose 但在这种情况下,我需要在主视图控制器视图上添加 uinaviagtioncontroller 视图,对吗?
  • 它可以是不同的设备,但主要是表格视图位于顶部站点和底部,我有类似容器视图的东西,我通过添加视图控制器视图来实现。
  • @MySpecialPurpose 我喜欢导航的想法,所以我可以添加一个视图,然后推送另一个视图控制器
  • 当我将 navigationcontroller 视图作为 suview 添加到我的视图中时,我的框架出现了问题,我使用此代码,然后我可以看到整个视图 [_containerNavigationController.view setFrame:CGRectMake(247, 64, 10000, 10000 )];如果我使用 700 作为高度,我推送的视图将被切断,但它的视图大小为 700 x 700。你是否遇到过同样的问题

标签: ios uiviewcontroller


【解决方案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),那么您需要在这里有一些更复杂的逻辑代码。

不做太多假设,但为了给您一些一般指导,当您创建一个单元格时,您通常会在其上设置某种标志以指示它是什么类型。如果您只有两种状态,这可以使用 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;
        }
    }

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

【讨论】:

  • 请检查我正在寻找的来源bitbucket.org/matrosovDev/ios-manage-few-view-controllers你能评论一下吗?
  • 我检查了你的代码。尝试将您的视图控制器设置为从 UIViewController.m 中的 UINavigationController 继承您通常不会将导航控制器放在子视图位置,它应该是根控制器并且应该负责。
  • 它可能会起作用。我只是从来没有那样用过。只需对其进行测试以确保它不会损坏,您应该会没事的。祝你好运!总是欢迎投票:)
【解决方案2】:

我建议使用 Storyboard 并确保为每个 Storyboard 设置一个“Storyboard ID”。这样,根据需要推送各种UIViewController 实例会变得更容易一些。这是我的典型模式:

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

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

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

【讨论】:

  • 如果您看到拆分视图控制器,这是我想问的问题。所以但它也适用于 iPhone,所以我们有一些组件,其中一个主要有 2 个视图,第二个用于显示另一个视图控制器,但每个视图都在屏幕上,所以用户每次都可以看到 2 个视图控制器的两个视图
  • 在这种情况下,您将设置多个故事板;一个用于 iPhone,一个用于 iPad,为每个设备创建适当的 UI。您不能在 iPhone 上同时显示 2 个UIViewController 实例。至少,UIViewController 实例是全屏的;
  • 请检查我已经实现了我正在寻找的资源bitbucket.org/matrosovDev/ios-manage-few-view-controllers。你能评论一下吗?
猜你喜欢
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多