为什么我似乎必须在iOS app delegate中对window.rootViewController进行类型转换?

时间:2012-05-08 03:40:15

标签: objective-c ios cocoa-touch ios5

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

UINavigationController被设置为Interface Builder中的初始视图控制器(我们还称它为Interface Builder?反正......)。 UINavigationController的rootViewController是一个通用的UITabBarController。

我想将主AppDelegate用于UINavigationController和UITabBarController委托。我已经让AppDelegate符合UINavigationControllerDelegate和UITabBarControllerDelegate。一切都很好。但是!

在AppDelegate的应用程序中: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吗?

2 个答案:

答案 0 :(得分:3)

调用属性

window.rootViewController

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

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

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

但明确表示一般情况良好。编译器不知道如何正确/安全地将消息-setDelegate:发送到UIViewController,这就是它抱怨的原因。你需要更明确地使用它。

答案 1 :(得分:1)

请记住,当您致电self.window.rootViewController时,您实际上正在呼叫

[self.window rootViewController];

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

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

[self.window setRootViewController:(UIViewController *) aViewController];
在这里已经发生了类型转换。运行时也可以使用此方法来实现您在xib中声明的出口链接。

所以除了重新进行类比之外别无他法。 与rootNavigationController.topViewController

相同的情况