Thursday, October 4, 2012

Putting iOS5 (non-Auto Layout) and iOS6 (Auto Layout) together in the App


I was trying to figure out the best way to implement support in my application for iOS5 where I can't use Auto Layout, and in iOS6 where I can. Thanks to Apple Developer forum to get this answered.

From what I gather, it looks like I will need to have two storyboards in my project, one for iOS6 with Auto Layout turned on, and one for iOS5 where it is turned off. If this isn't the best approach, I'd be interested in hearing suggestions.

That said, if I proceed as above, I'm not understanding how at run time I tell the app (in code I'm guessing) which storyboard to use based on whether the app is running on a device with iOS6 or iOS5.

In the Application Summary tab, I set my "Main Storyboard" to my iOS 5-based storyboard. Then using code (below), I detect if I'm on a device with iOS 6, and if so, I change to my iOS 6-based storyboard. To select the correct storyboard on application launch, I added the following to my AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    NSString *reqSysVer = @"6.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    UIStoryboard *storyBoard;
    
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
        {
            storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
            UIViewController *initViewController = [storyBoard instantiateInitialViewController];
            [self.window setRootViewController:initViewController];
        }
    
    return YES;
}

Works like a charm!

Friday, September 14, 2012

Auto rotation implementation changed from iOS6 SDK



Autorotation is changing in iOS 6. In iOS 6, the shouldAutorotateToInterfaceOrientation: method of UIViewController is deprecated. In its place, you should use the supportedInterfaceOrientationsForWindow: and shouldAutorotate methods.

More responsibility is moving to the app and the app delegate. Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate. By default, an app and a view controller’s supported interface orientations are set to UIInterfaceOrientationMaskAll for the iPad idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom.

A view controller’s supported interface orientations can change over time—even an app’s supported interface orientations can change over time. The system asks the top-most full-screen view controller (typically the root view controller) for its supported interface orientations whenever the device rotates or whenever a view controller is presented with the full-screen modal presentation style. Moreover, the supported orientations are retrieved only if this view controller returns YES from its shouldAutorotatemethod. The system intersects the view controller’s supported orientations with the app’s supported orientations (as determined by the Info.plist file or the app delegate’s application:supportedInterfaceOrientationsForWindow: method) to determine whether to rotate.

The system determines whether an orientation is supported by intersecting the value returned by the app’s supportedInterfaceOrientationsForWindow: method with the value returned by the supportedInterfaceOrientations method of the top-most full-screen controller.

The setStatusBarOrientation:animated: method is not deprecated outright. It now works only if the supportedInterfaceOrientations method of the top-most full-screen view controller returns 0. This makes the caller responsible for ensuring that the status bar orientation is consistent.

For compatibility, view controllers that still implement the shouldAutorotateToInterfaceOrientation: method do not get the new autorotation behaviors. (In other words, they do not fall back to using the app, app delegate, or Info.plist file to determine the supported orientations.) Instead, the shouldAutorotateToInterfaceOrientation: method is used to synthesize the information that would be returned by the supportedInterfaceOrientations method.

It took me long to understand this but managed to come out with the solution to get our existing Apps rotation stuff working with iOS 6.0 SDK and Xcode 4.5 GM. 

The existing apps which are targeted lower version will probably keep working until Apple totally removes auto rotation stuffs but if you compile your project against iOS 6.0 SDK, it will stop working and you have to accept following solution.

Steps to get auto rotation working.

1. First thing get rid of shouldAutorotateToInterfaceOrientation: method from everywhere 
2. if you don't have RootViewController in your project then you will have to setup one.
3. Copy paste following code in rootviewcontroller implementation and enjoy.

- (BOOL)shouldAutorotate 
return YES; 

- (NSUInteger)supportedInterfaceOrientations 
return UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown; 
}

You can use UIInterfaceOrientationMaskAll to support all orientation