If my project supports iOS versions 4.3 and up, how can I enable autolayout in iOS6 only, but disable it to the lower versions?
if you are using storyboards, create two storyboards, one with auto-layout on, and other with auto-layout off. Then one way to check is to load either one based on os version.
i used this little macro
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:(v) options:NSNumericSearch] != NSOrderedAscending)
this should work too (probably better in some cases then above):
if ([NSLayoutConstraint class]) {
// >= 6.0
} else {
// < 6.0
}
and then in my appDelegate:
UIStoryboard *mainStoryboard = nil;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.0"))
{
mainStoryboard = [UIStoryboard storyboardWithName:#"AutoLayoutStoryboard" bundle:nil];
}
else
{
mainStoryboard = [UIStoryboard storyboardWithName:#"NoAutoLayoutStoryboard" bundle:nil];
}
//load initial view controller
UIViewController *rootView = [mainStoryboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = rootView;
[self.window makeKeyAndVisible];
ADD: if you are using nibs, and want to enable auto-layout for iOS6 only, you can create a storyboard (or nibs) with auto-layout on, and load them using above version check
Either you should use two xib files or you should check it programmatically before writing code of auto layouts and constraints.
Related
I'm trying to create 2 storyboards, one for iPhone 4 and one for iPhone 5. I want it to be detected at launch which device the user is using. I've used the following code and implemented it in my app delegate.m, but receive the error:
Use of undeclared identifier "initializeStoryBoardBasedOnScreenSize"
Here's the code I've used:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
-(void)initializeStoryBoardBasedOnScreenSize {
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{ // The iOS device = iPhone or iPod Touch
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if (iOSDeviceScreenSize.height == 480)
{ // iPhone 3GS, 4, and 4S and iPod Touch 3rd and 4th generation: 3.5 inch screen (diagonally measured)
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone35
UIStoryboard *iPhone35Storyboard = [UIStoryboard storyboardWithName:#"Storyboard_iPhone35" bundle:nil];
// Instantiate the initial view controller object from the storyboard
UIViewController *initialViewController = [iPhone35Storyboard instantiateInitialViewController];
// Instantiate a UIWindow object and initialize it with the screen size of the iOS device
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Set the initial view controller to be the root view controller of the window object
self.window.rootViewController = initialViewController;
// Set the window object to be the key window and show it
[self.window makeKeyAndVisible];
}
if (iOSDeviceScreenSize.height == 568)
{ // iPhone 5 and iPod Touch 5th generation: 4 inch screen (diagonally measured)
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone4
UIStoryboard *iPhone4Storyboard = [UIStoryboard storyboardWithName:#"Storyboard_iPhone4" bundle:nil];
// Instantiate the initial view controller object from the storyboard
UIViewController *initialViewController = [iPhone4Storyboard instantiateInitialViewController];
// Instantiate a UIWindow object and initialize it with the screen size of the iOS device
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Set the initial view controller to be the root view controller of the window object
self.window.rootViewController = initialViewController;
// Set the window object to be the key window and show it
[self.window makeKeyAndVisible];
}
} else if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
{ // The iOS device = iPad
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
}
Is there maybe something I need to import to fix the error?
You have tried to define a method inside application:didFinishLaunchingWithOptions::
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
-(void)initializeStoryBoardBasedOnScreenSize {
// ... your code ...
}
return YES;
}
This is not what you want and btw. nested functions (or methods) are not supported
in Objective-C.
What you probably meant is to define a method and call it
inside application:didFinishLaunchingWithOptions::
-(void)initializeStoryBoardBasedOnScreenSize {
// ... your code ...
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self initializeStoryBoardBasedOnScreenSize];
return YES;
}
maybe it could just be an error here, but you're entering an action void in didFinishApplicationLaunchingWithOptions?
did you try to fit everything in didFinishApplicationLaunchingWithOptions without simply use this action void?
So I've created an app for iPhone and I wanted to convert it to iPad, by following steps from this answer.
Duplicate your iPhone-Storyboard and rename it MainStoryboard_iPad.storyboard
Open this file any text editor.
Search for targetRuntime="iOS.CocoaTouch"and change it to targetRuntime="iOS.CocoaTouch.iPad"
Now save everything and reopen Xcode -> the iPad-Storyboard contains the same as the iPhone-file but everyting could be disarranged
Everything is done correctly but iPad simulator/device anyways uses iPhone storyboard. Any suggestions?
I've set iPad storyboard in summary->ipad deployment info->Main storyboard. And main.plist-> Main storyboard file base name (iPad) is set to iPad storyboard.
Please tell me what I am missing.
UPD. Interesting Thing, when I delete iPad storyboard name from ipad deployment info it still uses my iPhone storyboard on device.
You could always pick the proper storyboard in the appDelegate and present the appropriate root view controller programatically
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
UIViewController *rvc;
}
Implementation
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"IPAD_Storyboard" bundle:nil];
rvc = [storyboard instantiateViewControllerWithIdentifier:#"identifierForController"];
}
else {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
rvc = [storyboard instantiateViewControllerWithIdentifier:#"identifierForController"];
}
[self.window addSubview:rvc.view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Dont forget to add following things in project's info.plist file (Main Storyboard file base name/ Main Storyboard file base name (iPad))
Hope this helps.
Just as an app utilizes different storyboards for iPad and iPhone, I would like my app to use a different storyboard for the iPhone 5. Since there is no option in the Info.plist to select default storyboard for iPhone 5, how would I programmatically call the storyboard?
I do not want to use AutoLayout for this app unless it is absolutely the last resort. I understand how to detect if a user is using an iPhone 5 or other device with the same screen size. I just need to know how to set the default storyboard without the plist.
I was looking for the same answer couple of weeks ago here's my solution hope helps..
-(void)initializeStoryBoardBasedOnScreenSize {
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{ // The iOS device = iPhone or iPod Touch
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if (iOSDeviceScreenSize.height == 480)
{ // iPhone 3GS, 4, and 4S and iPod Touch 3rd and 4th generation: 3.5 inch screen (diagonally measured)
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone35
UIStoryboard *iPhone35Storyboard = [UIStoryboard storyboardWithName:#"Storyboard_iPhone35" bundle:nil];
// Instantiate the initial view controller object from the storyboard
UIViewController *initialViewController = [iPhone35Storyboard instantiateInitialViewController];
// Instantiate a UIWindow object and initialize it with the screen size of the iOS device
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Set the initial view controller to be the root view controller of the window object
self.window.rootViewController = initialViewController;
// Set the window object to be the key window and show it
[self.window makeKeyAndVisible];
}
if (iOSDeviceScreenSize.height == 568)
{ // iPhone 5 and iPod Touch 5th generation: 4 inch screen (diagonally measured)
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone4
UIStoryboard *iPhone4Storyboard = [UIStoryboard storyboardWithName:#"Storyboard_iPhone4" bundle:nil];
// Instantiate the initial view controller object from the storyboard
UIViewController *initialViewController = [iPhone4Storyboard instantiateInitialViewController];
// Instantiate a UIWindow object and initialize it with the screen size of the iOS device
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Set the initial view controller to be the root view controller of the window object
self.window.rootViewController = initialViewController;
// Set the window object to be the key window and show it
[self.window makeKeyAndVisible];
}
} else if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
{ // The iOS device = iPad
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
}
}
Call this method under AppDelegate ddiFinishLaunchingWithOptions: method
And also don't forget the name your storyboards properly
Hope helps...
This worked for me - slight refinement with wrapping getting the storyboard in a function
-(UIStoryboard*) getStoryboard {
UIStoryboard *storyBoard = nil;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPad" bundle:nil];
}else{
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone){
// The iOS device = iPhone or iPod Touch
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if (iOSDeviceScreenSize.height == 480){
// iPhone 3/4x
storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone_4" bundle:nil];
}else if (iOSDeviceScreenSize.height == 568){
// iPhone 5 etc
storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone_5" bundle:nil];
}
}
}
ASSERT(storyBoard);
return storyBoard;
}
UIStoryboard* mainStoryBoard = [self getStoryboard];
self.initialViewController = [mainStoryBoard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.initialViewController;
[self.window makeKeyAndVisible];
I am trying to convert my iPhone only application to a Universal application. I switched the devices to Universal and let Xcode do it's thing making a MainWindow-iPad.xib for me, and now when I run the app in the iPhone simulator it works fine, but when I run it in the iPad simulator I get a white screen and the Application windows are expected to have a root view controller at the end of application launch error. I have read some other posts about this same problem but none of them are just limited to one device.
Here is my application:didFinishLaunchWithOptions: method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
/* some dropbox setup stuff */
// INIT VIEW AND CORE DATA
RootViewController *rootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
NSManagedObjectContext *context = [self managedObjectContext];
if (!context) {
// Handle the error.
}
rootViewController.managedObjectContext = context;
UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.navigationController = aNavigationController;
[_window addSubview:[_navigationController view]];
[_window makeKeyAndVisible];
[rootViewController release];
[aNavigationController release];
return YES;
}
EDIT: I just have one root view controller that is sized for iPhone called RootViewController. But it should still load in shouldn't it? Or if it shouldn't how do I create one for iPad?
Change the following line:
[_window addSubview:[_navigationController view]];
to:
_window.rootViewController = _navigationController;
or, if you need iOS 3 compatibility:
if ([_window respondsToSelector:#selector(setRootViewController:)]) {
_window.rootViewController = _navigationController;
} else {
[_window addSubview:_navigationController.view];
}
You need to create a RootViewController with the xib file for iPad, otherwise you will get this error. Below are the template code provided by Xcode for universal app. If you debug the app in iPad simulator and point the debugger to run create the view controller with iPhone xib file, you will see the exact error.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[SYKViewController alloc] initWithNibName:#"SYKViewController_iPhone" bundle:nil];
} else {
self.viewController = [[SYKViewController alloc] initWithNibName:#"SYKViewController_iPad" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
In iOS 4 and later, UIWindow has the settable property rootViewController. This is the UINavigationController that pushes the UIViewController displayed on application launch. In Xcode IB, selecting Initial Scene: Is initial view controller for the UINavigationController sets everything up with no code required.
From the generated MainWindow-iPad.xib, in Interface Builder, add a View Controller object in IB, as well as an Object underneath the View. For the object, set it's class to AppDelegate, for the View Controller, set the class to ViewController (i the Identity Inspector) and specify the nib name in the Attributes Inspector. You can look at the MainWindow.nib for the device you were converting from to see the differences.
Edit: I forgot to mention some important steps. You will also need to set the File's Owner class to "UIApplication" in IB, and set the referencing outlets appropriately for the App Delegate and View Controller. Again, in IB, it's easiest to look at the Connections Inspector for the MainWindow nib you had and emulate it. If you have another nib specific to the iPad, other than MainWindow-iPad.nib (i.e. ViewController-iPad.nib), be sure to select it's File's Owner and point it to the view and set it's class appropriately too.
I tried your suggestions but none of them worked for me, sorry. :/ I ended up just making the view manually in code without interface builder:
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
// Setup view for iPad
} else
// Setup view for iPhone and iPod Touch
}
which I thought would be a lot harder than it actually was.
Note that if you use this method you can still hook up everything in interface builder and just change the frame of objects in these blocks if you are going to have the same objects on both iPhone and iPad.
I am using XCode 4.0.
I am Transiting from my iPhone App to IPad as a universal app?
I have some doubts for xib files?
Should I use the autoresize element for each UIElement?
Or
Trasit each xib file to the ipad xib file?
How? Could not get the option for that?
.
Use different .xib files for iPad and iPhone and initWithNibName:bundle:. Determine whether to use one or another using this block
NSString *nibName = nil;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
nibName = #"CustomViewControllerIpad";
}
else {
nibName = #"CustomViewControllerIphone";
}
CustomViewController *viewController = [[CustomViewController alloc] initWithNibName:nibName bundle[NSBundle mainBundle]];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];