Reputation: 166
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
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
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