带有嵌套视图控制器的 iOS 自定义导航

Posted

技术标签:

【中文标题】带有嵌套视图控制器的 iOS 自定义导航【英文标题】:iOS custom navigation with nested view controllers 【发布时间】:2011-03-24 22:49:38 【问题描述】:

我不确定这样做的最佳做法,所以我想我会问。

这是该计划的目标:

通过根 UIViewController 创建的自定义导航控制器,它实际上不是 UINavigationController 的子类(便于操作设计) 不同屏幕的嵌套视图控制器(由主视图控制器操作) 每个嵌套视图控制器都有自己的 nib 文件

目前,我可以使用它,但是每个嵌套视图控制器都不是视图控制器,而是 UIView 的子类。我觉得这是不好的做法,因为我以视图控制器的方式使用这些 UIView,但没有视图控制器的功能(即 viewDidLoad)。此外,这些 UIView 采用了 UIViewController 的常用委托方法(这确实引发了危险信号)。

这真的是不好的做法吗?

当我尝试切换到 UIViewControllers 时,我害怕的事情是我仍然需要创建 UIView 的子类来确定当我通过以下方式加载 nib 时要指向哪个视图:

NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];

for (id object in bundle) 
    if ([object isKindOfClass:[SubclassedUIView class]])
        currentScreenViewController = (SubclassedUIView *)object;

我还没有检查,但我认为我必须在该语句中执行“SubclassedUIView”,而不仅仅是 UIView,因为捆绑包中还有其他 UIView 对象。但话又说回来,这种情况可能比现在要好。

另一种解决方案可能是让 MainViewController 成为所有需要委托的 UIView 的委托,并创建 MainViewController 的类别,其中包含每个嵌套 nib 的委托方法。

这里有什么想法吗?

【问题讨论】:

【参考方案1】:

为每个SubclassedUIView 类型创建一个UIViewController 子类,勾选为接口创建一个XIB 文件的选项,并将所有代码移到该文件上,将其指向self.view。然后使用该视图控制器的 .xib 打开 Interface Builder,并根据需要配置 UIView 的视觉外观。要从主视图控制器操作可视元素,您必须为每个元素分配“标记”编号,或者创建一大堆 IBOutlet 实例变量并将它们连接到 IB 中的元素。使用UINavigationController 正确呈现视图控制器的方式是:

/* at the top of your main view controller */
#import "SubclassedUIViewController.h"

/* when navigating to the next view */
SubclassedUIViewController *newController = [[SubclassedUIViewController alloc] initWithNibName:@"SubclassedUIViewController" bundle:nil];
[(UILabel *)[newController.view viewWithTag:6] setText:@"Text"]; // example of accessing elements using tags
[newController.textLabel setText:@"Text 2"]; // example of accessing elements using IBOutlet connections
[self.navigationController pushViewController:newController animated:YES];
[newController release];

Interface Builder 还允许您将导航控制器添加到主视图控制器 .xib 文件并提供后退按钮文本、主标题等。当您实现子类视图控制器时,覆盖 initWithNibName:bundle: 并设置 self.navigationItem.title以及您想要的self.navigationItem 的任何其他属性。

编辑:您的意思是您必须能够在其他子类视图中操作某些子类视图的特定属性吗?例如,您需要始终访问所有这些?如果是这种情况,则在加载主视图控制器时连接到您的子类视图,即:

- (void)viewDidLoad

    [super viewDidLoad];
    self.subclassedController1 = [[SubclassedUIViewController1 alloc] initWithNibName:@"SubclassedUIViewController1" bundle:nil];
    // self.subclassedController2 = ... etc


/* in your loading next view code you can skip the alloc/init line */
[self.navigationController presentViewController:subclassedController2 animated:YES];

然后在您的子类控制器中,您可以通过以下几种方式访问​​主控制器:

    致电self.parentViewController[(MyCustomAppDelegateClass *)[[NSApplication sharedApplication] delegate] rootView] 或类似的调用(基本上,您的应用程序委托对应用程序主视图的引用)。 通过将@property (assign) 属性和ivar 添加到指向主视图控制器的子类控制器。您可以在使用 subclassedController1.mainViewController = self 加载主视图控制器时分配它。

有用的文档:

    View Controller Programming Guide for ios: Navigation Controllers Xcode Quick Start Guide(针对 Xcode 4 更新)

【讨论】:

对不起 - 我不想继承 UINavigationController,因为它是限制性的。稍微编辑了我的问题以反映这一点已明确。 我上面写的所有内容都可以由普通的非子类UINavigationController处理。我谈论的子类是您使用默认导航控制器推送和弹出的内容。甚至根视图控制器也只是UIViewController 的子类。导航控制器本身实际上是在主窗口的 Interface Builder 界面中定义的,作为根视图控制器的主视图的子视图。 我想做同样的事情,但假设 UINavigationController 不是要走的路,因为你不能指定下一个控制器如何转换。例如,push/pop 从左右控制他们的动画,但我想要更多地控制它。我制作了一个可以工作的原型,但我认为当集成到我的代码库中时它会出现多线程问题,因为我的原型项目不再工作了。我怀疑 UINavigationController 中发生了一些复杂的事情,而 UIViewController 无法做到。我不知道。 我发现这个链接很好地解释了您的问题和潜在的解决方案:Abusing UIViewControllers【参考方案2】:

显然,根据How to add an UIViewController's view as subview,我正在做的事情还不错。

【讨论】:

你也可以从另一个帖子***.com/questions/17499391/…查看解决方案

以上是关于带有嵌套视图控制器的 iOS 自定义导航的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 导航控制器和自定义视图

自定义 UIView XIB 内的 iOS 导航返回按钮(无导航控制器)

如何将自定义导航栏链接到导航控制器?

带有自定义后退导航按钮的自定义按钮栏

Ios 导航 - 自定义后退按钮或从堆栈中删除视图控制器?

如何在 Swift iOS 中自定义导航控制器