UINavigationController not updating size with auto layout iOS 8 - ios

I'm trying to update my app to be compatible with iOS8 I found some bugs in the App with the Autolayouts of the UINavigationController when I rotate the device to landscape mode the root view updates but the subviews doesn't update even the sub-views of the Scrollview.
The App is for iPhone and iPad so I use two separate storyboards and I use this code
- (void)viewDidLoad {
[super viewDidLoad];
self.shouldAdjustChildViewHeightForStatusBar = NO;
[self setNeedsStatusBarAppearanceUpdate];
UIStoryboard *storyboard;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
storyboard = [UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil];
}
self.topViewController = [storyboard instantiateViewControllerWithIdentifier:#"HomeController"];
}
The image
Below is the view as you see is in landscape mode an there is a big white space because the Scrollview did not update or something
I use to update the subview but the scroll did not work.
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{

It's unclear from your question but it looks like you are subclassing ECSlidingViewController.
If you look at the source for ECSlidingViewController, it only lays out the topViewController in its viewDidLoad.
Solution 1:
You want the topViewController to be set before viewDidLoad is called, and they do it in awakeFromNib:
- (void)awakeFromNib {
[super awakeFromNib];
UIStoryboard *storyboard;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
storyboard = [UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil];
}
self.topViewController = [storyboard instantiateViewControllerWithIdentifier:#"HomeController"];
}
Solution 2
They seem to have a nice convenience method to initialize a sliding view controller. Wherever you are creating your ECSlidingViewController, you could rather do:
UIStoryboard *storyboard;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
storyboard = [UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil];
}
UIViewController *topViewController = [storyboard instantiateViewControllerWithIdentifier:#"HomeController"];
ECSlidingViewController *slidingViewController = [ECSlidingViewController slidingWithTopViewController:topViewController];
// ...

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

UIStoryboard calling issues for diffrent device size

I want to call UIStoryboard for three diffrent device (iphone4s,iphone5 and ipad). I have newly added for iphone4s device. I have the following Storyboard
Main_iPhone
Main_iPhone4(newly added)
Main_iPad
Please check my current source. Its working working with iphone5.
AVCamViewController *vc = [[UIStoryboard
storyboardWithName:#"Main_iPhone" bundle:NULL]
instantiateViewControllerWithIdentifier:#"rootController"];
vc.modalPresentationStyle = UIModalPresentationFormSheet;
vc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self.viewControllerCam presentViewController:vc animated:YES completion:nil];
I need to change like below and i was run with iphone4s device. but still im seeing "Main_iPhone" storyboard. PLease help me how to switch Main_iPhone4 when i was run in iphone4s device.
UIStoryboard *storyboard = nil;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if (iOSDeviceScreenSize.height == 480)
{
storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone4" bundle:nil];
}
if (iOSDeviceScreenSize.height == 568)
{
storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
}
}
else if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
storyboard = [UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil];
}
AVCamViewController *vc = [storyboard instantiateInitialViewController];
vc.view.backgroundColor = [UIColor clearColor];
vc.modalPresentationStyle = UIModalPresentationFormSheet;
vc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self.viewControllerCam presentViewController:vc animated:YES completion:nil];
Your code seems fine and it should work according to that.
But this is not the right way to manage separate storyboard for iPhone 4s & iPhone 5/5s. Instead you can manage using single storyboard for both and arrange the layout using auto-layout, I'm sure it will reduce your lot of work.

Opening a ECSlidingViewController from a non ECSlidingViewController

I have tried reaching a ECSlidingViewController on IBAction. However when I tried the below code:
-(IBAction)openNewPage:(id)sender{ //IV
UIStoryboard *storyboard;
ECSlidingViewController *slidingViewController = (ECSlidingViewController *)[storyboard instantiateViewControllerWithIdentifier:#"IV"];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
storyboard = [UIStoryboard storyboardWithName:#"iPhone" bundle:nil];
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
storyboard = [UIStoryboard storyboardWithName:#"iPad" bundle:nil];
}
slidingViewController.topViewController = [storyboard instantiateViewControllerWithIdentifier:#"FirstTop"];
}
I get the following error:
'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
I tried a modal action on the button, the 'touchupinside' will land at the InitialViewController. Any suggestions on this?
You need to move the line where you define slidingViewController to below your if-else-if clause because storyboard will be nil where you currently do it.
UIStoryboard *storyboard;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
storyboard = [UIStoryboard storyboardWithName:#"iPhone" bundle:nil];
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
storyboard = [UIStoryboard storyboardWithName:#"iPad" bundle:nil];
}
ECSlidingViewController *slidingViewController = (ECSlidingViewController *)[storyboard instantiateViewControllerWithIdentifier:#"IV"];
slidingViewController.topViewController = [storyboard instantiateViewControllerWithIdentifier:#"FirstTop"];

iPhone 5 screen adapt

I am using this code to adapt my storyboard depending on device (iphone 5 or less):
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
if(UIScreenOverscanCompensationScale==1136/640){
//move to your iphone5 storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"iphone5 storyboard" bundle:[NSBundle mainBundle]];
}
else{
//move to your iphone4s storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:[NSBundle mainBundle]];
}}
The code doesn't work even if I just place:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"iphone5 storyboard" bundle:[NSBundle mainBundle]];
...it still loads iphone normal.
I put it under:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
in app delegate. Is this right?? In the app settings I chose the original iphone storyboard
The problem is that:
UIScreenOverscanCompensationScale==1136/640
will never be true.
Check what UIScreenOverscanCompensationScale is doing and return a BOOL.
Is MainStoryboard still specified under target summary? I believe that this will be where the app looks first.
I managed to solve it in this way:
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 568.0){
//move to your iphone5 storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"iphone5 storyboard" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
// Set root view controller and make windows visible
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
else{
//move to your iphone4s storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
// Set root view controller and make windows visible
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}}

Resources