Two Xibs one UIViewController crashing on iPad - ipad

I have a strange problem.
I have 2 XIBs and 1 ViewController. The One XIB ist for iPhone the other for iPad.
In the XIB for iPad there are just bigger images.
- (void)pressShare:(UIBarButtonItem *)sender
{
NSString *nibName = #"";
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
nibName = #"MCComunicationViewController";
}
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
nibName = #"MCComunicationViewControlleriPad";
}
MCComunicationViewController *comVC = [[MCComunicationViewController alloc] initWithNibName:nibName bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:comVC];
navController.navigationBar.tintColor = [MCColorFactory emerald];
navController.navigationBar.barTintColor = [UIColor whiteColor];
[self.navigationController presentViewController:navController animated:YES completion:nil];
}
On iPhone 5 with iOS 7.1 its working perfectly on iPad with iOS 7.1 it's crashing.
Debugger on iPad running says
po navController
<UINavigationController: 0x16578470>
po navController.viewControllers
<__NSArrayI 0x16590390>(
<MCComunicationViewController: 0x165780d0>
)
po comVC
<MCComunicationViewController: 0x165780d0>
It's crashing with SIGABRT in main.m and when I Debug step by step it's crashing by [self.navigationController presentViewController:navController animated:YES completion:nil]; :/ Any ideas?

For using two xib , user Container class.
If you are using container you can easy to manage data.

Try ....
[self.navigationController pushViewController:navController animated:YES];

Related

dismissViewControllerAnimated issue

The first screen of my app consists of the login screen. I am displaying the login screen from AppDelegate.
The login screen comes up and I am able to go to next screen in the simulator. But it doesn't work on device.
On device, the main screen comes up for a second and the login screen is displayed. I tried changing the order of [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil]; and [self.window.rootViewController presentViewController:self.navigationController animated:YES completion:nil]; but that doesn't work either.
I am running on a iOS 9.0 iPad (device). Everything seems fine on simulator though.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = nil;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self->_loginViewController = [[LoginViewController alloc] initWithNibName:nil bundle:nil];
self.window.rootViewController = nil;
self.window.rootViewController = self->_loginViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)loginUser {
if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
//load xib for iPad
mainVC = [[MainVC alloc] initWithNibName:#"MainVC~ipad" bundle:nil];
} else if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
//load xib for iPhone
mainVC = [[MainVC alloc] initWithNibName:#"MainVC~iphone" bundle:nil];
}
self.navigationController = nil;
self.navigationController = [[UINavigationController alloc] initWithRootViewController:mainVC];
dispatch_async(dispatch_get_main_queue(),^ {
// [self.window.rootViewController.navigationController popViewControllerAnimated:YES]; //not working
[self.window.rootViewController dismissViewControllerAnimated:YES completion:nil]; //not working
[self.window.rootViewController presentViewController:self.navigationController animated:YES completion:nil];
//not working
// [self.window.rootViewController.presentingViewController dismissViewControllerAnimated:YES completion:^{
// [self.window.rootViewController presentViewController:self.navigationController animated:YES completion:nil];
// }];
});
}
First thing is you are setting up LoginViewController as the rootController of the window which is fine. In your login method you are trying to dismiss a controller when none is presented here(assuming you have not presented any other controller). You can remove that line and just present the navigation controller.
For this purpose, I normally change my rootViewController. In your case, when your user has logged on replace:
[self.window.rootViewController dismissViewControllerAnimated:YES completion:nil]; //not working
[self.window.rootViewController presentViewController:self.navigationController animated:YES completion:nil];
with:
self.window.rootViewController = self.navigationController;
And then on user logout do:
self.window.rootViewController = self.loginViewController;

Present UIViewController as UIModalPresentationFormSheet & UIModalPresentationOverCurrentContext

How do I present a UITableViewController with a blurred background as a form sheet over the current context?
- (void)viewDidLoad {
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.backgroundView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
}
It works fine full screen, on iPhones set with UIModalPresentationOverCurrentContext
But for iPad if I want to display it as a form sheet then I need to set modalPresentationStyle to UIModalPresentationFormSheet.
How do I set both?
I found I needed to use UIModalPresentationPopoverfor the modalPresentationStyle and then you can set the view controllers popoverPresentationColor to clearColor.
FAGalleryTableViewController *vc = (FAGalleryTableViewController *)[segue destinationViewController];
if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
vc.modalPresentationStyle = UIModalPresentationPopover;
vc.popoverPresentationController.sourceView = _storeButton;
vc.popoverPresentationController.backgroundColor = [UIColor clearColor];
vc.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionDown;
vc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
}
After searching so much, this worked for me on iOS10+
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
//IPAD
CamVC *destination = segue.destinationViewController;
[destination setModalPresentationStyle:UIModalPresentationFullScreen];
[destination setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
}else{
// IPHONE
CamVC *destination = segue.destinationViewController;
destination.modalPresentationStyle = UIModalTransitionStyleCrossDissolve;
destination.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
}

UINavigationController not updating size with auto layout iOS 8

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];
// ...

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.

How to switch to different Storyboard for iPhone 5?

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];

Resources