I am attempting to use both storyboards for my iOS project, but I cannot get the code to switch to the appropriate storyboards. Instead, the code does absolutely nothing. Is it that I do not have a setting set correctly that controls the switch? The main storyboard for devices not of the iPhone 5, is called MainStoryboard. The iphone 5 appropriate layout is called iphone5. I'm thinking this may be a project configuration setting issue. (This is in my appdelegate.m file).
-(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:#"MainStoryboard" 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:#"iphone5" 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;
}
}
I suggest just using 1 storyboard for handling the iPhone 5 vs iPhone 3-4S screen sizes.
When your Storyboard is open, there is a button at the bottom that toggles between the 2 sizes-- you can see in real-time how things will look.
The button is to the left of the Zoom in % Zoom out buttons in the bottom right corner, and looks like this:
To handle how your object's frame & position will be affected by the screen size change-- you need to set the autosizing properties for each object in your view. You can do this by selecting an object, and in the right Inspector panel, Select the Size inspector like so:
You see those red lines in the Autosizing box? Play around with them to see how they will effect your object. The inner ones relate to the size (if the width, or height stretches), and the outer ones relate to the position.
I'm not sure about your apps layout but from experience you will probably have to mess with the inner vertical line (how the height will change), and the bottom line (you want that to stay near the bottom).
The more you mess around with each the more you will see what each does.
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?
I have created an app that contain two Xib file one for iPhone 4 And one for iPhone5. iphone 5 screen look ok but in iphone 4 it will different.
Here is the xib file for iPhone 4
And here is the simulator screen.
My xib file size is 320*460. i dont have idea about this behavior. can any one plz help.
UPDATE
I am presenting my VC using this code
TransactionDetailViewController * transactionDetailViewController;
//select the zib according to the screen size
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568) {
transactionDetailViewController = [[TransactionDetailViewController alloc] initWithNibName:#"TransactionDetailViewController" bundle:nil];
} else {
transactionDetailViewController = [[TransactionDetailViewController alloc] initWithNibName:#"TransactionDetailViewController_iPhone4" bundle:nil];
}
// Pass the selected object to the new view controller.
self.navigationController.navigationBar.tintColor = [UIColor redColor];
[self.navigationController pushViewController:transactionDetailViewController animated:YES];
You are loading iPhone 5 nib both the time. take a isIpad global flag set it depending upon the device then use this init method in your view controller
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSString *nibName=nil;
nibName=isiPad?#"viewController_iPhone5":#"viewController";// isIpad is flag set if device is iPhone5
self = [super initWithNibName:nibName bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
The iPhone 4 screen is not resizing or scaling correctly and therefore some of the content is behind the tab bar.
The standard size for the tab bar is 49 high and the nav bar is 44 high. You could resize the view to be 320 x 367 as this is 460 - 49 - 44.
This is not the best solution admittedly but it may just work
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 have the starter point of my application this window (white background):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
mainScreen = [[MainScreenController alloc] initWithNibName:#"MainScreenController" bundle:[NSBundle mainBundle]];
// add it to the main window
[window addSubview:[mainScreen view]];
// show view
[window makeKeyAndVisible];
NSLog(#"started");
return YES;
}
And MainScreenController is an UIViewController with (blackBackground) created by the Interface Builder.
The application executes perfectly but the first time, the black view is moved up like the height of the status iphone pannel (leaving white rectangle at the bottom).
If I rotate the iPhone twice, the view is perfectly positioned in the right place, filling all the screen with the black background.
Any idea?
Thanks!
Check your MainScreenController settings in IB. You should select a simulated status bar element (cmd-1) so that the view is positioned below the status bar initially.
EDIT - Why are you calling the initWithNibName in your delegate here? Most of the app templates I've used had the main view nib initialized by the OS and you use IB and set an IBOutlet in the main VC interface. You probably have an initial frame origin of {0,0} after calling initWithNibName. Add these lines after your initWithNibName call to verify this:
NSLog(#"mainscreen frame=%#", NSStringFromCGRect(mainscreen.view.frame));
CGRect frame = mainscreen.view.frame;
frame.origin.y = 20; // move below status bar
mainscreen.view.frame = frame;