Richard Calahan
Richard Calahan

Reputation: 166

Why do I seemingly have to typecast window.rootViewController in iOS app delegate?

I have a fairly simple iOS 5 app at this point.

A UINavigationController is set as the initial view controller in Interface Builder (do we still call it Interface Builder? anyways...). The UINavigationController has as its rootViewController a generic UITabBarController.

I want to use the main AppDelegate for both the UINavigationController and UITabBarController delegate's. I've made the AppDelegate conform to both the UINavigationControllerDelegate and UITabBarControllerDelegate. Everything works well. BUT!

In AppDelegate's application:didFinishLaunchingWithOptions:, I feel like I'm doing something hacky. I'm having to typecast self.window.rootViewController, and self.window.rootViewController.topViewController in order to set each controllers delegate.

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

If I don't typecast self.window.rootViewController I can't set it's delegate. Same for the topViewController (UITabBarController).

If I've declared in Inferface Builder that the initial view is a UINavigationController, and not some generic UIViewController, why must I still typecast everything? Is this hacky?

Upvotes: 0

Views: 1482

Answers (2)

ZeR0
ZeR0

Reputation: 331

keep in mind that when you call self.window.rootViewController you are actually calling

[self.window rootViewController];

it's a method which returns a UIViewController object. and the rootViewController property declared in UIWindow Class is belong to Class UIViewController.

The UIWindow object wouldn't know which class its rootViewController property is belong to, because setting the property is actually calling

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

typecast has already happened here. The runtime would also use this method to implement outlet links you declared in xib.

So there's no way but to re-typecast it. same case as rootNavigationController.topViewController

Upvotes: 1

jbrennan
jbrennan

Reputation: 12003

Calling the property

window.rootViewController

returns an instance of UIViewController, and that class does not have a publicly visible property called delegate. UINavigationController, however, does.

When using property syntax (i.e., dot notation) the compiler needs to know which properties the receiver's class has declared.

If you instead do the standard message notation and don't cast, [rootViewController setDelegate:self], then it will probably work, but I believe you'll get a compiler warning still, but it will "work".

But it's generally good to be explicit. The compiler doesn't know how to properly/safely send the message -setDelegate: to UIViewController, that's why it complains. You need to be more explicit with it.

Upvotes: 3

Related Questions