Sending a message to a subview after autorotate
I have a fairly simple view hierarchy in my iPad app.
Window -> RootView -> TableView / DetailView
TableView and DetailView are siblings added as subviews (as per a solution to a previous question). On launch TableView is in front. When you select a cell then method in the app delegate is called which swap them out putting DetailView at the front. A close button in DetailView does the reverse.
Works great.
However... DetailView contains a UIScrollView, drawn in the .xib When DetailView comes to the front I have a method that receives details of the contents of the cell whose selection triggered the change. This populates the detail view with label contents and an image. The labels are simple setters to IBOutlets to the labels in the .xib The image is sized to the height of the UIScrollView, maintaining aspect ratio. This is done programatically, adding it to an UIImageView which is added to the UIScrollView.
The behaviour I have is fine for Portrait. When it rotates to Landscape I want to resize the image to match the width of the enclosing UIImageView (and subsequently the enclosing UIScrollView). I have some great code to actually resize the image (courtesy of a category addition to UIImage from [link text][1]
THE PROBLEM... Only the RootViewCont开发者_如何学Croller responds to calls to didRotateToInterfaceOrientation. I need to send a message from this to a method on the DetailViews controller telling it to resize the image then redraw the associated UIImageView. Referencing the controller of a subview seems like it should be simple and possibly i'm missing an easy answer. I tried to use:
[[self.view.subviews objectAtIndex:1] didRotateFromInterfaceOrientation:fromInterfaceOrientation];
and
[self.view viewWithTag:[[self.view.subviews objectAtIndex:1] tag]]
But they both return the view NOT the views controller, and therefore get all angry about selectors when I try to run it.
Can anyone point me the right way?
Sigh. seems the process of writing out the question helped me formulate it better in my mind and find the answer...
Reference the Application Delegate which already has connections to the view controllers...
[[(AppDelegate *)[[UIApplication sharedApplication] delegate] detailViewController] methodToCall];
The best way to get rotation methods invoked on all your View Controllers is to use an Apple supplied Root View Controller and display any child views through those controllers. These include UINavigationController, UITabBarController, and on the iPad UISplitViewController.
Navigation events will only get sent to the root view controller, that is the view controller of the view in the main UIWindow of your app. This is not documented, but can be deduced with some work. Apple's root view controllers seem to be capable of propagating rotation events.
This can be achieved manually (i.e. without an Apple RVC) but requires keeping track of all your child VCs and using KVC on some readonly properties, which would likely get you kicked out of the app store.
In your case you could use a navigation controller, hiding the navigation bar and toolbar as appropriate. Initialize it with your current root view controller and add the navigation controller view to the window, instead of your current root view controller. When you need to display the details, simply push the details on the navigation stack. If you don't like the default animation you can apply your own transition with a little work.
See below for more details on the navigation controller.
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UINavigationController_Class/Reference/Reference.html
精彩评论