切换 UINavigationController 层次结构的块并保留导航栏

发布于 2024-11-28 11:30:11 字数 2637 浏览 1 评论 0原文

这有点啰嗦,但我认为最好还是说清楚。我似乎找不到确定的方法来做到这一点,而且问题很微妙(我认为)。

我有一个应用程序,其 GUI 层次结构类似于:

  • 主列表(具有自定义 TableCell 和高度)
    • 子列表(针对选定的主列表项目)
      • 子列表信息(在选定的子列表项上)
        • 更多信息
    • 设置(针对选定的主列表项)
      • 设置信息(在选定的设置项上)
        • 更多信息

一旦选择了主列表项,用户就可以在子列表和设置之间切换,每个子列表都有自己的 GUI 子层次结构。该切换是使用工具栏进行的。

我尝试了几种方法,但似乎没有一种方法完全正确。

第一次尝试(受到其他问题的启发)

  • UINavigationController
    • UITableViewControllerBase(从笔尖加载)
      • TableViewController1(以编程方式加载到 didSelectRowAtIndexPath)
      • TableViewController2(可以与 TableViewController1 交换)

我在创建各种对象时传递对 rootViewController 的引用,然后使用它来进行切换。

[rootViewController switchViews]

在 rootViewController.switchViews() 中:

[TableViewController2 alloc] init];
[TableViewController1 removeFromSuperview];
[self.view insertSubview:TableViewController2.view atIndex:0]
. . .

基本上,rootViewController 管理切换。这适用于开关,但是当我通过层次结构导航回主列表时,它无法正确初始化表格单元格。

在 cellForRowAtIndexPath: 中,

static NSString *CellId = @"CellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIDentifier:CellId];
if (cell == nil)
{
  ... (this does not get called)
}

因为括号中的代码没有被调用,所以表视图看起来“通用”,即不使用自定义单元格。虽然这可能是一个不相关的错误,但这里的整个方法对我来说似乎并不正确。我的理解是活动视图控制器应该处理切换。所以我尝试了一些不同的东西。 。 。

第二次尝试(受到《iPhone 编程入门》一书的启发):

  • UINavigationController
    • UITableViewControllerBase(从笔尖加载)
      • UIViewControllerParent(以编程方式加载到 didSelectRowAtIndexPath)
        • TableViewController1(以编程方式加载到父级的 loadView 上)
        • TableViewController2(可以与 TableViewController1 交换)

这里,我们将两个嵌套的表视图包含在控制器父级中,并让父级完成所有工作。

在父级的 loadView() 中:

TableViewController1 *tvc1 = [[UITableViewController alloc] init];
self.tableViewController1 = tvc1;
[self.view insertSubview:tableViewController1.view atIndex:0];
[tvc1 release];

这里的问题是 tableViewController1 虽然已初始化,但在插入时没有有效的视图。因此 loadView 函数被一次又一次地调用。 。 。我也尝试将此代码放入 viewDidLoad 中,同样的问题。

我从 iOS 开发者网站阅读了示例代码 TheElements,最初打算走这条路。问题是,用户在我的应用程序中切换视图后,他可以深入查看更多屏幕。我希望所有这些屏幕都成为应用程序层次结构的一部分(以便我们可以在需要时返回主列表)。虽然 TheElements 说明了一个切换,但它只是在单个 UIViewController 中切换视图 - 我需要能够在切换到新屏幕后向下钻取,并使所有这些屏幕成为 UINavigationViewController 层次结构的一部分,以用于导航目的。

我对这一切都很陌生,所以我可能以错误的方式思考事情。因此就有了这个问题。我确信这种设计有些常见,所以尽管毫无疑问有很多方法可以做到这一点,但我正在寻找最佳实践。这里的关键是,切换完成后,用户应该能够在 UINavigationViewController 的层次结构中进一步向下导航,并且能够向上导航。这需要加载多个 UIViewController。我相信。

非常感谢您抽出时间(并对冗长的帖子表示歉意)。

This is somewhat long-winded, but I think better to be clear. I can't seem to find the definitive way to do this, and the problem is subtle (I think).

I have an application whose GUI hierarchy looks something like:

  • Main List (has a custom TableCell and height)
    • Sub List (for a selected Main List item)
      • Sub List Info (on a selected Sub List item)
        • Further info
    • Settings (for a selected Main List item)
      • Settings Info (on a selected Settings item)
        • Further info

Once a main list item is selected, the user is able to swap between Sub List and Settings, each of which have their own GUI sub-hierarchy. The switch is made using a toolbar.

I've tried several approaches and nothing seems to work exactly right.

First try (inspired by other questions here)

  • UINavigationController
    • UITableViewControllerBase (loaded from nib)
      • TableViewController1 (loaded programmatically on didSelectRowAtIndexPath)
      • TableViewController2 (can be swapped from TableViewController1)

I pass a reference to the rootViewController through as the various objects are created, then use that to do the switch.

[rootViewController switchViews]

In rootViewController.switchViews():

[TableViewController2 alloc] init];
[TableViewController1 removeFromSuperview];
[self.view insertSubview:TableViewController2.view atIndex:0]
. . .

Basically, rootViewController manages the switch. This works for the switch, but when I navigate back through the hierarchy to the Main List, it doesn't initialize the table cells properly.

In cellForRowAtIndexPath:

static NSString *CellId = @"CellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIDentifier:CellId];
if (cell == nil)
{
  ... (this does not get called)
}

because the code in the brackets doesn't get called, the table view looks "generic", that is, the custom cell is not used. While this might be an unrelated error, the whole approach here didn't seem right to me. My understanding is that the active view controller should be handling the switch. So I tried something different . . .

Second try (inspired by Beginning iPhone Programming book):

  • UINavigationController
    • UITableViewControllerBase (loaded from nib)
      • UIViewControllerParent (loaded programmatically on didSelectRowAtIndexPath)
        • TableViewController1 (loaded programmatically on parent's loadView)
        • TableViewController2 (can be swapped from TableViewController1)

Here we're enclosing both the nested table views in a controller parent, and letting the parent do all the work.

In loadView() of parent:

TableViewController1 *tvc1 = [[UITableViewController alloc] init];
self.tableViewController1 = tvc1;
[self.view insertSubview:tableViewController1.view atIndex:0];
[tvc1 release];

The issue here is that tableViewController1, although inited, does not have a valid view at the time when it's being inserted. So the loadView function gets called again and again . . . I also tried putting this code in viewDidLoad, same problem.

I read the example code TheElements from the iOS developer site, and was originally going to go that route. The problem is that after the user switches views in my application, there's more screens that he can drill down into. I want all those screens to be part of the application's hierarchy (so that we can go back to the Main List when we want to). While TheElements illustrates a switch, it just switches views in a single UIViewController - I need to be able to drill down after the switch to new screens and have all those screens be a part of the UINavigationViewController's hierarchy, for navigation purposes.

I'm new to all this so it's possible I'm thinking of things in the wrong way. Hence the question. I'm sure this design is somewhat common, so even though there are undoubtedly many ways to do it, I'm looking for the best practice. The key thing here is that after the switch is made, the user should be able to navigate further down in the UINavigationViewController's hierarchy, and be able to navigate back up. That requires loading multiple UIViewControllers. I believe.

Many thanks for the time (and apologies for the long post).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ゞ记忆︶ㄣ 2024-12-05 11:30:11

所以,如果我正确理解你的问题,你想在导航控制器堆栈顶部的两个视图控制器之间切换。为什么不让导航控制器完成工作并使用 setViewControllers:animated: 来替换现有数组中的最后一个视图控制器。

例如,带有额外的翻转动画(在 SubListViewController 中):

- (void)switchToSettings:(id)sender
{
    [UIView transitionWithView:self.navigationController.view duration:1.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^ {
        SettingsViewController *settingsVC = [[[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
        settingsVC.mainListItem = self.mainListItem;
        NSMutableArray *mutableViewControllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
        [mutableViewControllers removeLastObject];
        [mutableViewControllers addObject:settingsVC];
        [self.navigationController setViewControllers:mutableViewControllers animated:NO];
    } completion:^(BOOL finished) {}];
}

So, if I understand your question correctly, you want to switch between two view controllers at the top of a navigation controller's stack. Why don't you just let the navigation controller do the work and use setViewControllers:animated:, replacing just the last view controller in the existing array.

Example, with an additional flip animation (in SubListViewController):

- (void)switchToSettings:(id)sender
{
    [UIView transitionWithView:self.navigationController.view duration:1.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^ {
        SettingsViewController *settingsVC = [[[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
        settingsVC.mainListItem = self.mainListItem;
        NSMutableArray *mutableViewControllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
        [mutableViewControllers removeLastObject];
        [mutableViewControllers addObject:settingsVC];
        [self.navigationController setViewControllers:mutableViewControllers animated:NO];
    } completion:^(BOOL finished) {}];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文