为什么UITableViewController不应该管理Cocoa Touch窗口的一部分?

4
我有一个包含UITableViewUILabel的视图,据我所知它完美地工作。但我真的不想像UITableViewController一样管理UIViewUITableView,因为UITableViewController处理了很多事务,并且根据文档

如果要管理的视图是由多个子视图组成的复合视图,其中一个表格视图是其中之一,则必须使用自定义的UIViewController子类来管理该表格视图(以及其他视图)。不要使用UITableViewController对象,因为此控制器类将调整表格视图的大小以填充导航栏和选项卡栏之间的屏幕(如果存在)。

为什么Apple警告不要使用它?如果我忽略这个警告会发生什么?

更新:最初我引用了Apple文档中的以下内容:

您不应使用视图控制器来管理仅填充其窗口的部分视图,即仅填充应用程序内容矩形定义区域的一部分。如果要拥有由多个较小视图组成的界面,请将它们全部嵌入单个根视图中,并使用您的视图控制器来管理该视图。

虽然这个问题可能与为什么UITableViewController被设计为全屏有关,但它并不完全相同。


我认为你已经回答了自己的问题。 - Stefan Arentz
一个相关的问题是关于将UITableView与其他视图组合的问题。值得注意的是Cocoa with Love的这篇博客文章,介绍了如何重新创建UITableViewController - Casebash
4个回答

7
只使用一个视图控制器来管理每个屏幕的主要实际原因是这是唯一管理导航的方法。
例如,假设您有一个包含两个单独视图控制器的屏幕,并且您使用导航控制器加载它。您将推哪个视图控制器以及如何加载和引用第二个视图控制器?(更不用说同时协调两个分离的控制器的开销了。)
我认为使用单个自定义控制器并不像您想象的那样麻烦。
请记住,“TableviewDataSource”和“TableViewDelegate”无需在实际控制器中。苹果模板只是为了方便而这样做。您可以将实现两个协议的方法放在一个类中或将它们分别放在自己的类中。然后,您只需将它们与自定义控制器中的表格链接起来即可。这样,所有自定义控制器需要做的就是管理tableview本身的框架。所有配置和数据管理都将在单独且自包含的对象中。如果您需要从其他UI元素获取数据,则自定义控件可以轻松地向它们发送消息。
这种灵活性,定制性和封装性正是为什么首先使用委托设计模式的原因。您可以自定义任何东西而无需创建一个做所有事情的大型类。相反,您只需弹出委托模块并开始使用。
编辑01:回应评论
如果我正确理解您的布局,则您的问题是UITableViewController硬编码为设置表以填充可用视图。大多数情况下,tableview本身就是顶部视图,这很有效。UITableViewController的主要功能是定位表格,因此,如果您使用非标准布局,则不需要它。您可以只使用通用视图控制器,并让nib设置表的框架(或通过编程方式设置)。正如我所说,很容易认为委托和数据源方法必须在控制器中,但实际上并不需要。您应该完全摆脱tableViewController,因为它在您的特定设计中没有作用。

UIView 包含 UITableView,因此 UIView 由导航控制器加载,而表格是视图的一部分,并且在 xib 文件中与我的 TableViewController 相连接。 - Casebash
请查看上面答案正文中的Edit01。 - TechZen
如果我正确理解了你的布局,你的问题在于UITableViewController被硬编码为将表格设置为填充可用视图 - 如果我尝试使用UITableView来控制UIView,那将是一个问题。然而,通过我的当前设置,一切都正常工作。我只是对这个警告感到好奇。 - Casebash
1
不,您必须嵌套控制器,并且其行为已经有很好的文档记录。关键在于您必须拥有一个明确定义的层次结构,其中一个单一的顶级控制器。这是导航、选项卡和分割视图控制器的工作原理。一个控制器必须对整个可见屏幕负有最终责任。如果您尝试设置两个相等的控制器,则系统会崩溃。 - TechZen
无论视图有多复杂,对于单个静态视图很少需要多个控制器。通过使用委托模式,您不必将 UI 元素的所有功能都塞进一个控制器中。您可以拥有一个管理基本布局的控制器,然后使用各种委托对象来管理各个 UI 元素。 - TechZen
显示剩余2条评论

3
对我来说,苹果文档中的重要细节是他们建议你不要使用“视图控制器”(即UIViewController实例或其子类)来管理仅填充窗口一部分的视图。对于非全屏视图,使用几个(自定义)控制器没有问题,只是它们不应该是UIViewController对象。
UIViewController期望其视图占据整个屏幕,如果不是这样,可能会得到奇怪的结果。当它出现时,视图控制器调整视图大小以适合窗口(减去导航栏和工具栏),它管理设备方向(如果其视图不占据整个屏幕,则很难正确应用)等。因此,考虑到UIViewController的工作方式,我认为苹果的建议有价值。
但是,这并不意味着您不能编写自己的控制器类来管理子视图。除了上面提到的事情外,与选项卡栏和导航控制器交互以及接收内存警告之外,UIViewController并没有太多要做的事情。您可以编写自定义控制器类(从NSObject子类化),在“正常”全屏视图控制器中实例化它,并让它处理与您的视图的交互。
我看到的唯一问题是响应者链。视图控制器是响应者链的一部分,因此您的视图不处理的触摸事件会转发到视图控制器。据我所知,没有简单的方法将自定义控制器放在响应者链中。我不知道这对您是否相关。如果您可以使用目标-操作机制管理与视图的交互,则无关紧要。

2
我有一个应用程序,在其中我使用了两个单独的UIViewController子类来管理表格视图和工具栏,它“差不多”能够工作,但是由于这样做导致了一些麻烦,我现在意识到不应该使用UIViewController子类来管理子控制器,因为它们包含了我不需要的行为,且妨碍了我的开发。
出现问题的主要是以下几点:
  • 从子导航返回时视图的奇怪调整以及viewWillLoad和viewDidLoad之间几何计算的差异等。

  • 当我不应该释放子视图控制器时,难以处理低内存警告。

预期UIViewController子类不会被用于此类情况,而它们处理事件的方式、使用导航控制器等方式使得尝试在同一页中使用多个UIViewController子类变得棘手,因为你最终花费的时间更多是在绕过其行为。

-3
在我看来,苹果的方式是为您提供“一种”解决方案。这非常适合最终用户。没有选择,没有头痛。
我们是程序员,我们想要和需要自定义。然而,在某些情况下,苹果仍然不希望我们做太多的更改。例如,选项卡栏、工具栏和导航栏的高度,UI组件(表视图)的一些默认大小,一些默认行为等等。当设计一个框架和一套API时,他们需要确定一些决策。即使它是一个非常好的和灵活的设计,世界上总有一个程序员想要做一些不同的事情,并发现难以针对设计实现。
简而言之,你想要在同一个屏幕上放置一个表视图和一个标签,但他们不这么认为。 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接