Support iOS 4 devices while building with the iOS 6 SDK

Apple has released iOS 6.0 SDK alongside the iPhone 5.  It comes with a number of changes (and deprecations) from previous SDK’s.  We still needed to support iOS 4 in our product (backwards compatibility), but had a large number of customers clamoring for iPhone 5 support (full screen).  Apple rejects any applications that are submitted with support for iPhone 5 that aren’t built with the iOS 6 SDK, so it was necessary to do a few tricks to support both iOS 4 and the new iPhone 5.

First our product has “Treat all errors as warnings” enabled, this meant that a number of deprecated functions that have been used all over the place (dismissModal, presentModal, etc…) are now throwing warnings and those warnings are treated as errors.  So it was necessary to add a build flag to the build settings in X-Code to not warn about deprecations (Under build settings change “Warn about Deprecated Functions” to no), this ignored all the errors that were related.  This was necessary because we couldn’t remove these errors from the code, as for most of the deprecated functions, there are no replacements until iOS 5, so if iOS 4 support is desired, we have to continue to use the old deprecated methods.

Next, the minimum target had to be changed to iOS 4.3 (Goodbye iPhone 3G support) but we still have support for other devices running 4.3 =< and iPhone 3GS > (Here is a matrix).

Finally, apple changed the way rotation works, and it was necessary to “hotwire” all of our existing rotation code into the new code.  shouldAutorotateToInterfaceOrientation: is the old way of checking rotation, and would be called (even when compiled with iOS 6 SDK) on any device that was running iOS < 6.  However this method would not be called for iOS 6 devices, instead it would look for the shouldAutorotate and supportedInterfaceOrientations methods, and extract it from there.  Rather then go through the 100+ view controllers we have with custom implementations for shouldAutorotateToInterfaceOrientation: I created a #define that would insert itself into the code for shouldAutorotateToInterfaceOrientation, and define the two new methods (should Autorotate and supportedInterfaceOrientations) so that they would query the old method and return an updated result.

I placed the following code in our Prefix file:

#ifdef __IPHONE_6_0 // Only do the rotation fix if we are building with iOS 6 API
@protocol DeprecatedRotationSupported
@optional
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toOrientation;
- (BOOL)shouldAutorotate;
- (NSUInteger)supportedInterfaceOrientations;
@end

#define shouldAutorotateToInterface_fixed shouldAutorotate \
{ \
    UIViewController  *selfTyped = (UIViewController  *) self; \
\
    if(![self respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) \
        return NO; \
    int optionCount = 0; \
    for(UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait; orientation <= UIDeviceOrientationLandscapeLeft; orientation++) \
    { \
        if(![selfTyped shouldAutorotateToInterfaceOrientation:orientation]) continue; \
        if(optionCount==1) return YES; \
        optionCount++; \
    } \
    return NO; \
} \
\
- (NSUInteger)supportedInterfaceOrientations \
{ \
    UIViewController  *selfTyped = (UIViewController  *) self; \
\
    if(![self respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) return UIInterfaceOrientationMaskPortrait; \
    \
    NSUInteger supported = 0; \
    \
    if([selfTyped shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) supported |= UIInterfaceOrientationMaskPortrait; \
    if([selfTyped shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft]) supported |= UIInterfaceOrientationMaskLandscapeLeft; \
    if([selfTyped shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight]) supported |= UIInterfaceOrientationMaskLandscapeRight; \
    if([selfTyped shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortraitUpsideDown]) supported |= UIInterfaceOrientationMaskPortraitUpsideDown; \
    return supported;  \
} \
\
- (BOOL)shouldAutorotateToInterfaceOrientation
#else // We are building with the older API, leave shouldAutorotateToInterfaceOrientation alone.
#define shouldAutorotateToInterface_fixed shouldAutorotateToInterfaceOrientation
#endif // __IPHONE_6_0

Then, I did a replace all for shouldAutorotateToInterfaceOrientation: with shouldAutorotateToInterface_fixed: like below:

- (BOOL)shouldAutorotateToInterface_fixed:(UIInterfaceOrientation)toInterfaceOrientation

Also, make sure if you are using addSubview to add your main view to the window that you use setRootViewController instead.

No Comments

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

WordPress Themes