为什么苹果不允许对UINavigationController进行子类化?有没有其他替代方案可以使用?

12

我目前正在构建一个选项卡式的iPhone应用程序,在该应用程序中,每个选项卡的视图控制器都是UINavigationController的实例,而每个UINavigationController实例的每个子控制器都是UITableViewController的实例。理想情况下,我希望能够对UINavigationController进行子类化,使得每个选项卡的控制器都是UINavigationController的子类,除了具有所有标准的UINavigationController功能外,还充当与其子控制器相关的每个表视图的数据源和代理。但是尝试这样做似乎会破坏子类中基本的UINavigationController功能。

由于苹果在其iPhone文档中说不应该对UINavigationController进行子类化,并且在进行子类化时似乎会出现问题,因此我想知道如何在不进行子类化的情况下扩展UINavigationController的功能,以及在进行Cocoa开发时如何解决子类化限制问题。

谢谢!


1
我自己也很好奇,我看到苹果的UINavigationController文档现在说明:“这个类通常是按原样使用的,但在iOS 6及更高版本中可以被子类化。” - bneely
6个回答

21

你为什么要让UINavigationController作为表格的数据源呢?使用UITableViewController的主要目的是通过子类化来充当UITableView的数据源,并将其放置在父视图中并填充它。


1
同意。在这种情况下,苹果只是在帮助您避免糟糕的设计决策。如果您真的认为有一个更好的想法,那么可以自己从头编写控件。 - Azeem.Butt
这个。没有任何理智的理由去子类化UINavigationController。UINavigationController实际上并没有控制任何真正可修改的UI。表视图控制器的整个重点在于它控制内容。你的表视图控制器应该是将数据从它的模型视图适配到表视图的东西。此外,一个单一的控制器控制着许多不同的表视图听起来像是一场灾难的等待。我建议不要这样做,不是因为子类化,而是因为这听起来是最复杂的方式。 - Colin Cornaby

10

我认为你的想法有一定的价值,如果每个层级都使用相同类型的数据,并且每个层级可能有不同的委托来处理单元格的创建。

基本上,你可以子类化UINavigationController来添加一个完全正交的数据层,因为它与UINavigationController正在管理的UI或行为无关(这是苹果公司担心你会搞砸的内容)。对于那些反对这个想法的人来说,可以将其视为每个选项卡的数据存储,所有选项卡中的页面都可以访问它,而不是系统中的每个页面都必须到AppDelegate去获取,或者拥有一堆单例。实际上,这是一个单例,但至少是一个已经存在并自动传递引用的单例。

话虽如此,我将以一种替代的设计提案结束 - 我认为你可能想要通过多个层级进行钻取,重复使用相同的代码来生成单元格,因为每个层级都具有相同类型的数据。处理这种情况的更好方法是有一个视图控制器,你给它提供要显示的子集数据,当用户钻取时,它只需使用新的子集数据创建另一个相同的视图控制器实例。该方法比让导航控制器作为每个层级的表格委托更好,因为你需要来回进行大量的重连,并且还需要更多的工作来记住每个层级的滚动位置。这就是为什么你要保持钻取使用多个视图控制器实例,但多个实例并不一定意味着多个类。


明白了。感谢您的澄清和建议。 - Matthew McCroskey

10

需要注意的是,从iOS 6开始,UINavigationController可以被合法地继承。

通常情况下,这个类不需要被继承,但是在iOS 6及以后的版本中可以进行继承。 UINavigationController类参考

当然,并不意味着您总是应该这样做。但您是可以这样做的。


1

如果现有的控制器层次结构不能满足您在处理数据方面的需求(这是我的假设,因为我们不知道为什么您希望一个对象成为多个视图的数据源),您始终可以创建额外的数据和/或控制器类(至少是 NSObject 的子类)。

您可以通过各种方式使数据或其他对象在更改视图时保持持久性。(1)您的应用委托类的属性。您的应用程序中的任何对象都可以获取您的应用委托实例:

[[UIApplication sharedApplication] delegate]

使用这个要谨慎,因为它本质上是在创建全局变量。

(2) 当您推入视图控制器子类或在选项卡中打开它们时,您可以传递数据或其他对象从控制器到控制器。

(3) Core Data 是另一种方式,但需要熟练掌握 Cocoa,并且仍然需要管理上下文实例。


1
据我所知,不鼓励使用子类化,因为Objective C允许子类对其超类的内部工作具有过多的访问权限。
编写代理是编写子类的建议替代方案,在这种情况下是UINavigationControllerDelegate。然后,您可以将要扩展的特定行为封装到此代理类中,并在需要时将其链接到UINavigationController。

0

因为他们想要避免其他平台所困扰的UI不一致性。


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