为啥我似乎必须在 iOS 应用程序委托中键入 window.rootViewController?

Posted

技术标签:

【中文标题】为啥我似乎必须在 iOS 应用程序委托中键入 window.rootViewController?【英文标题】:Why do I seemingly have to typecast window.rootViewController in iOS app delegate?为什么我似乎必须在 iOS 应用程序委托中键入 window.rootViewController? 【发布时间】:2012-05-08 03:40:15 【问题描述】:

此时我有一个相当简单的 ios 5 应用程序。

UINavigationController 被设置为 Interface Builder 中的初始视图控制器(我们仍然称它为 Interface Builder 吗?无论如何...)。 UINavigationController 有一个通用的 UITabBarController 作为它的 rootViewController。

我想将主 AppDelegate 用于 UINavigationController 和 UITabBarController 委托。我使 AppDelegate 符合 UINavigationControllerDelegate 和 UITabBarControllerDelegate。一切正常。但是!

在 AppDelegate 的 application:didFinishLaunchingWithOptions: 中,我觉得我在做一些 hacky。为了设置每个控制器委托,我必须对 self.window.rootViewController 和 self.window.rootViewController.topViewController 进行类型转换。

UINavigationController *rootNavigationController = (UINavigationController *) self.window.rootViewController;
UITabBarController *rootTabBarController = (UITabBarController *) rootNavigationController.topViewController;
[rootNavigationController setDelegate:self];
[rootTabBarController setDelegate:self];

如果我不进行类型转换 self.window.rootViewController 我无法设置它的委托。 topViewController (UITabBarController) 也一样。

如果我在 Inferface Builder 中声明初始视图是一个 UINavigationController,而不是一些通用的 UIViewController,我为什么还要对所有内容进行类型转换?这是 hacky 吗?

【问题讨论】:

你在尝试[self.window.rootViewController setDelegate:self]时得到了什么? "'UIViewController' 没有可见的@interface 声明选择器 setDelegate。"它不会编译。 【参考方案1】:

调用属性

window.rootViewController

返回UIViewController 的实例,并且该类没有名为delegate 的公开可见属性。但是,UINavigationController 可以。

当使用属性语法(即点表示法)时,编译器需要知道接收者的类声明了哪些属性。

如果您改为使用标准消息表示法而不进行转换,[rootViewController setDelegate:self],那么它可能会work,但我相信您仍然会收到编译器警告,但它会“工作”。

但通常最好是明确的。编译器不知道如何正确/安全地将消息-setDelegate: 发送到UIViewController,这就是它抱怨的原因。你需要更明确地处理它。

【讨论】:

嗯,有趣的是,我明确声明“初始视图控制器”是 InterfaceBuilder 中的 UINavigationController。这个声明与 self.window.rootViewController 无关吗? 不,它绝对相关的。在 iOS 5 故事板中,初始视图控制器最终成为 UIWindow 实例中的 rootViewController【参考方案2】:

请记住,当您拨打 self.window.rootViewController 时,您实际上是在拨打电话

[self.window rootViewController];

这是一个返回 UIViewController 对象的方法。 UIWindow 类中声明的rootViewController 属性属于UIViewController 类。

UIWindow 对象不知道它的 rootViewController 属性属于哪个类,因为设置属性实际上是在调用

[self.window setRootViewController:(UIViewController *) aViewController];

typecast 已经在这里发生了。运行时也会使用这个方法来实现你在 xib 中声明的出口链接。

所以没有办法,只能重新排版。 与rootNavigationController.topViewController相同的情况

【讨论】:

以上是关于为啥我似乎必须在 iOS 应用程序委托中键入 window.rootViewController?的主要内容,如果未能解决你的问题,请参考以下文章

为啥/何时我必须点击两次才能触发 iOS 上的点击

Swift UI 委托方法不起作用

为啥我从后台工作人员调用的委托在主线程中运行

iOS 核心数据应用程序委托?

iOS 6 Beta 3 (ipad 3) 中的 UIAlertView 似乎不会触发委托中的代码

为啥我们需要 ios 中 UITABLEVIEW 的数据源和委托方法 [重复]