Understanding the Rotation Methods in UIViewController
The UIViewController
class provides several methods to handle rotation, including shouldAutorotateToInterfaceOrientation:
, willRotateToInterfaceOrientation:duration:
, willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
, willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
, and didRotateFromInterfaceOrientation:
. But who is responsible for dispatching these method calls? And how does the UIViewController
instance know which one to respond to?
The Role of UIApplication
According to Apple’s documentation, it is indeed the UIApplication
class that is responsible for forwarding messages related to rotation to the active view controller.
{< highlight objective-c >}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
// ...
}
In this code snippet, you can see how the UIApplication
class is dispatching a message when the interface orientation is about to change.
But how does the view controller instance receive these messages?
The Active View Controller
The answer lies in the concept of an “active” view controller. The UIApplication
class maintains an internal state that keeps track of which view controller has its view added to the UIWindow
instance.
{< highlight objective-c >}
// In UIApplication.m:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
// ...
// Get the active view controller
UIViewController *activeViewController = [self activeViewController];
// Forward the message to the active view controller
[activeViewController willRotateToInterfaceOrientation:interfaceOrientation duration:duration];
}
In this code snippet, you can see how the UIApplication
class is retrieving the active view controller before forwarding a message related to rotation.
Scenarios for View Controllers
There are three basic scenarios in which a view controller might receive these messages:
1. Single View App
In a single-view app, the view controller whose view is added directly to the UIWindow
instance will receive the messages related to rotation.
{< highlight objective-c >}
// In ViewController.m:
- (void)viewDidLoad {
// ...
// Add the view to the UIWindow instance
[[UIApplication sharedApplication] setMainWindow:[[UIWindow alloc] initWithScreenSize:UIRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)]];
}
In this code snippet, you can see how a single-view app adds its view to the UIWindow
instance and receives messages related to rotation.
2. Navigation Controller
In a navigation-based app with a navigation controller, the active view controller will receive the messages related to rotation.
{< highlight objective-c >}
// In NavController.m:
- (void)viewDidLoad {
// ...
// Set the main window
[[UIApplication sharedApplication] setMainWindow:self.window];
}
// In UIViewController.m:
- (void viewDidLoad {
// ...
// Get the navigation controller
UINavigationController *navigationController = [self navigationController];
// Forward the message to the active view controller
[navigationController.activeViewController willRotateToInterfaceOrientation:navigationController.interfaceOrientation duration:0];
}
In this code snippet, you can see how a navigation-based app sets its main window and receives messages related to rotation.
3. Tab Bar Controller
In a tab bar-based app with a tab bar controller, the active view controller will receive the messages related to rotation.
{< highlight objective-c >}
// In TabBar.m:
- (void)viewDidLoad {
// ...
// Set the main window
[[UIApplication sharedApplication] setMainWindow:self.window];
}
// In UIViewController.m:
- (void viewDidLoad {
// ...
// Get the tab bar controller
UITabBarController *tabBarController = [self tabBarController];
// Forward the message to the active view controller
[tabBarController.activeViewController willRotateToInterfaceOrientation:tabBarController.interfaceOrientation duration:0];
}
In this code snippet, you can see how a tab bar-based app sets its main window and receives messages related to rotation.
Conclusion
The UIViewController
class provides several methods to handle rotation, but who is responsible for dispatching these method calls? According to Apple’s documentation, it is indeed the UIApplication
class that is responsible. The view controller instance receives these messages by being registered as the active view controller in the UIWindow
instance.
By understanding how the UIApplication
class forwards messages related to rotation, developers can create apps with multiple views and ensure that their app responds correctly to changes in interface orientation.
Troubleshooting
One common issue that developers may encounter is when swapping views in and out of the UIWindow
instance manually. In this case, the view controller will not receive the messages related to rotation reliably.
To avoid this problem, it is recommended to use Apple’s conventions for multiple views, such as using a navigation controller or tab bar controller to manage multiple views.
By following these guidelines, developers can create apps that respond correctly to changes in interface orientation and provide a seamless user experience.
Last modified on 2023-08-12