Instantiating storyboard programmatically in appdelegate - ios

I decided to use different storyboards for ios6 and and ios7 and so I need to instantiate storyboards in code. I have this method in the app delegate´s - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
but nothing happens, it always just instantiate the storyboard named iPadStoryboardwhen run on the iPad simulator, I have deleted the Main interface´s from the info.plist. Any idea what´s happening here?
- (void)loadStoryboards
{
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
UIStoryboard *mainStoryboard = nil;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.0"))
NSLog(#"1");
if (iOSDeviceScreenSize.height == 480)
{
mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone-ios5" bundle:nil];
} else {
NSLog(#"loading iPad storyboard");
mainStoryboard = [UIStoryboard storyboardWithName:#"iPadStoryboardOS6" bundle:nil];
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
NSLog(#"2");
if (iOSDeviceScreenSize.height == 480)
{
mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
} else {
mainStoryboard = [UIStoryboard storyboardWithName:#"iPadStoryboard" bundle:nil];
}
self.initialViewController = [mainStoryboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.initialViewController;
[self.window makeKeyAndVisible];
}

Be careful how you check for iPad. 480px screen height doesn't cover iPhone5. Use:
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)

Related

Added iPad Storyboards, Now: "expected to have a root view controller..."

I've had an iPhone only app, built for the most part with the Interface builder.
I have a storyboard for each screensize/device.
In the AppDelegate, it selects the correct storyboard and loads it.
I've since redesigned my app and now adding iPad compatibility.
I've added two new storyboards, fixed their size to "iPad Full Screen" and "iPad Pro Full Screen".
I've copied in the existing iPhone Storyboards and ticked the first board as "Is Initial View Controller".
I've also followed THIS POST and opened storyboards as source code and updated the target from default to iPad.
When I launch the app on an iPad, i just get a black screen with the following error:
Application windows are expected to have a root view controller at the end of application launch.
Why is this happening?
This is the only thing I've changed in my AppDelegate to select the correct Storyboard:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIViewController *initialViewController = nil;
CGSize result = [[UIScreen mainScreen] bounds].size;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
if(result.height == 480){
NSLog(#"iPhone 3.5 Inch");
UIStoryboard *i4SB = [UIStoryboard storyboardWithName:#"iPhone35" bundle:nil];
initialViewController = [i4SB instantiateInitialViewController];
}
if(result.height == 568){
NSLog(#"iPhone 4 Inch");
UIStoryboard *i5SB = [UIStoryboard storyboardWithName:#"iPhone4" bundle:nil];
initialViewController = [i5SB instantiateInitialViewController];
}
if(result.height == 667){
NSLog(#"iPhone 4.7 Inch");
UIStoryboard *i47SB = [UIStoryboard storyboardWithName:#"iPhone47" bundle:nil];
initialViewController = [i47SB instantiateInitialViewController];
}
if(result.height == 736){
NSLog(#"iPhone 5.5 Inch");
UIStoryboard *i55SB = [UIStoryboard storyboardWithName:#"iPhone55" bundle:nil];
initialViewController = [i55SB instantiateInitialViewController];
}
//added iPad compatibility
if(result.height == 1024){
NSLog(#"iPad Mini(2,3,4) or iPad Air(1,2) or iPad(3,4) or iPad Pro(9.7inch)");
UIStoryboard *iPadMiniSB = [UIStoryboard storyboardWithName:#"iPadFull" bundle:nil];
initialViewController = [iPadMiniSB instantiateInitialViewController];
}
if(result.height == 1366){
NSLog(#"iPad Pro(12.9 Inch)");
UIStoryboard *iPadProSB = [UIStoryboard storyboardWithName:#"iPadPro" bundle:nil];
initialViewController = [iPadProSB instantiateInitialViewController];
}
}
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initialViewController;
[self.window makeKeyAndVisible];
return YES;
}
UPDATED / SOLUTION:
As Bharat Nakum mentioned below, you can remove the UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone condition.
Of course, you can also add an extra condition for iPad (which is what I did).
It now looks like this:
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
//set iPhone device storyboards here
}
else if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
//set iPad device storyboards here
}
This is also confirmed as an answer here.
Please remove this condition.
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
It is true only when device is iPhone.
So, your iPad storyboards are not initializing.
Hope this helps!

Show ViewController on different Storyboards

I have 3 storyboards for 3 different device screen size. I want to move from the main ViewController to the second ViewController when a button is pressed for the 3 storyboards. Here's the code:
In AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
UIStoryboard *storyBoard;
CGSize result = [[UIScreen mainScreen] bounds].size;
CGFloat scale = [UIScreen mainScreen].scale;
result = CGSizeMake(result.width * scale, result.height * scale);
if(result.height == 1136){
storyBoard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
else {
storyBoard = [UIStoryboard storyboardWithName:#"Main_iPhone4" bundle:nil];
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
}
return YES;
}
The code to move to second ViewController:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone/Main_iPhone4/Main_iPad" bundle: nil];
ArcadeView *svc = [storyboard instantiateViewControllerWithIdentifier:#"arcade"];
self.window.rootViewController = svc;
However, when i use the above code. XCode tells me
"Could not find a storyboard named
'Main_iPhone/Main_iPhone4/Main_iPad' in bundle NSBundle.
How do i fix this?
Because you don't have a storyboard with name #"Main_iPhone/Main_iPhone4/Main_iPad".
To make it work the way you want, do better in every storyboard make identical transitions and sign them the same identifier.
And for the transitions, use:
[self performSegueWithIdentifier:#"ShowMainMenu" sender:self]
But in general, I advise you to learn more about constraints. So it will be much easier

How to choose which Storyboard loads

I need to choose which MainViewController.h to load depending on the iPhone model that the app is running on. Using the code below, I distinguish between iPhone 4/4S and 5/5S/5C. Because of the auto layout, I will need to create two mainViewController.hs and then choose depending on the model of the phone. How do I do this? This is the code I have:
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
- (void)viewDidLoad
{
[super viewDidLoad];
if (IS_IPHONE_5) {
NSLog(#"Iphone 5");
} else {
NSLog(#"Iphone4");
}
}
So please tell me how to chose MainViewController.h.
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge|
UIRemoteNotificationTypeAlert|
UIRemoteNotificationTypeSound];
// Override point for customization after application launch.
return YES;
UIStoryboard *storyboard;
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height == 568) {
// iPhone 5
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone5" bundle:nil];
} else {
// iPhone 4
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone4" bundle:nil];
}
UIViewController *initialViewController = [storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initialViewController;
[self.window makeKeyAndVisible];
}
To specify which storyboard to load, do so in your AppDelegate's application:didFinishLaunchingWithOptions: method.
Load the storyboard that corresponds to the screen size using its storyboard name, ex:
UIStoryboard *storyboard;
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height == 568) {
// iPhone 5, i.e. 568 pixels high
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone5" bundle:nil];
} else {
// earlier model iPhones, i.e. 480 pixels high
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone4" bundle:nil];
}
UIViewController *initialViewController = [storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initialViewController;
[self.window makeKeyAndVisible];

FPPopover not showing

I'm implementing FPPopover into my application, it was working alright until I added some code to the app delegate to manage and display the correct storyboard depending on the device throughout the app. The code I added is as follows...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
UIStoryboard *storyboard = [self getStoryboard];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:#"Init"];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initViewController;
[self.window makeKeyAndVisible];
sleep(3);
return YES;}
-(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" bundle:nil];
}else if (iOSDeviceScreenSize.height == 568){
// iPhone 5 etc
storyBoard = [UIStoryboard storyboardWithName:#"Storyboard_iPhone_5" bundle:nil];
}
}
}
return storyBoard;}
If I delete all this code from my App delegate the popover works perfectly... But if I add it it doesn't work... I have no idea what is going on.
Can anyone help?
You don't need of this code..go in the project's general tab and set your storyboard for iPhone and iPad here:
In the storyboard you can select the inital view controller..
So you can delete all your code for storyboard and initial viewController
This is the code that i use in my appDelegate :) :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}

Load different Storyboard for iPhone 5 # app start

I am using the following code in my AppDelegate.m to detect which device the user is using:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480)
{
NSLog(#"iPhone 3,5 Inch");
[UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
}
if(result.height == 568)
{
NSLog(#"iPhone 4 Inch");
[UIStoryboard storyboardWithName:#"iPhone5-storyboard" bundle:nil];
}
}
return YES;
}
But when I build the App the NSLog is shown, but no Storyboard is coming up...
The Main Storyboard field in the Deployment info is empty so that the code decided what to load...
Can you help me?
Here is a way I now found on a other post:
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{ // The iOS device = iPhone or iPod Touch
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
UIViewController *initialViewController = nil;
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
initialViewController = [iPhone35Storyboard instantiateInitialViewController];
}
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
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;
}

Resources