Question

I have a really complex problem (or so I think). I'm working on a legacy application fixing some issues, and making it support 4 inch displays and iOS 7. The problem is that the app's architecture is quiet complex, with several categories and method swizzling to implement a custom look and feel in iOS 4.3 and 5.

The application is related to the financial markets and stock exchanges. The app is designed for being navigated in the portrait orientation only, except for a couple of controllers, where tilting the phone would change the view to the chart of the stock/market. The whole app has one UINavigationController, and in many places, a UITabBarControllers. In the controller I'm interested in, the structure is as follows:

  • UINavigationController
    • Orientation controller which changes the view if orientation changed
      • UITabBarController having several UIViewControllers
        • Market/Stock Controller in the first slot of the UITabBarController
      • Chart Controller

This structure used to work like this. When the phone is tilted, shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation (this was pre iOS 6) was called on my orientation controller (that has both UITabBarController and the chart controller), and it checks if the selectedIndex of the UITabBarController is the one for the market controller, or the stock controller, it replaces the view by the chart view for the landscape orientation.

After iOS 6, supportedInterfaceOrientations and shouldAutorotate were added to our code, and it worked fine as well. However, after upgrading to XCode 5 and building with iOS 7 as the base SDK, shouldAutorotate is not being called on my orientation controller, but it's being called on both the UITabBarController and the Market/Stock controller.

Any Ideas?

Was it helpful?

Solution 4

OK, my problem was somewhat a little bit more extraordinary. As I have mentioned in the question, the app is a legacy app, and it was written back when iOS 4 was pretty new, and it used to support iOS 3. Back then, window.rootViewController was not an option, since it's not compatible with iOS 3, and the way that you presented the root controller was to add it's view as a subview to the window like this [window addSubview:navigationController.view];. Seems that this way is not compatible with iOS7 (maybe even 6). The view showed up, and worked as expected, except that the system did not send orientation changes and never tried to auto-rotate the navigation controller. @Flexicoder's solution helped in detecting device orientation changes, but I still wasn't able to draw my chart controller correctly, because the navigation controller was never rotated. What @Igor & @Tamer mentioned didn't work first because of the way the view was added to the window, but after changing to the iOS 4+ method, it worked. Thanks again everyone.

OTHER TIPS

Subclass your navigation controller and override the method:

// CustomNavigationController.m

- (BOOL)shouldAutorotate {
    return [self.topViewController shouldAutorotate];
}

Then add shouldAutorotate method to the viewcontroller which should be rotated and return YES:

// ViewController.m

- (BOOL)shouldAutorotate {
    return YES;
}

Your Orientation controller could hook into UIDeviceOrientationDidChangeNotification Apple Docs

You also use the UIDevice instance to detect changes in the device’s characteristics, such as physical orientation. You get the current orientation using the orientation property or receive change notifications by registering for the UIDeviceOrientationDidChangeNotification notification. Before using either of these techniques to get orientation data, you must enable data delivery using the beginGeneratingDeviceOrientationNotifications method. When you no longer need to track the device orientation, call the endGeneratingDeviceOrientationNotifications method to disable the delivery of notifications.

I think the issue here if in UINavigationController the implementation shouldAutorotate is like this: - (BOOL)shouldAutorotate { return [self.topViewController shouldAutorotate]; }

then you should expect shouldAutorotate of topViewController to be called.

1- make sure that shouldAutorotate of the UINavigationController is called (expected yes).

2- if answer of first point is yes then check the type of the topViewController if it is not the OrientationController (expected yes also) then this is the problem.

so if this was the problem the fix will be changing the implementation of shouldAutorotate in the custom UINavigationController to be like this :

  • (BOOL)shouldAutorotate { for (UIViewController* controller in self.viewControllers) { if ([controller isKindOfClass:[OrientationController class]]) { [controller shouldAutorotate]; } } }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top