load different storyboard views in universal app from button xcode - objective-c

I am building a Universal iOS app.
I have several buttons on the main view which load other view controllers.
I have set up a "Main.storyboard" and an "iPad storyboard.storyboard".
I have made two views in the "main" and the "iPad".
On the "Main" I have set the Storyboard ID's to "FirstCar" and FirstPlayer".
On the "iPad" I have set them to "FirstCarPad" and FirstPlayerPad".
In the General settings I have designated the app as Universal and set the "Main" as the storyboard for the iPhone and the "iPad" for the iPad.
I am using the following code to launch the view controllers in the storyboards from the initial view.
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
int height = [UIScreen mainScreen].bounds.size.height;
if (height == 568.0) {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"FirstCar"];
[self presentViewController:vc animated:YES completion:NULL]; }
}
else if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad){
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"ipad storyboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"FirstCarPad"];
[self presentViewController:vc animated:YES completion:NULL]; }
When I tap the first button that accesses the "FirstCar" and "FirstCarPad"
ViewControllers everything works fine but
When I tap the second button that accesses the "FirstPlayer" and "FirstPlayerPad"
viewControllers the app crashes with this
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard () doesn't contain a view controller with identifier 'FirstPlayerPad''
but I have the viewControllers set up the exact same with the Storyboard ID
I am about to tear my hair out.
Can anybody help me out.

To get this to work I duplicated the Main.storyboard in the finder renaming it Main-iPad.storyboard then added it to the project. I then right clicked on the new storyboard and chose Open Source. This showed the storyboard as code and I changed targetRuntime="iOS.CocoaTouch" to targetRuntime="iOS.CocoaTouch.iPad". I then right clicked it again but chose Open Storyboard.
With the settings set to "Universal" and Main-iPad.storyboard selected as the iPad's storyboard everything works fine. I just have to resize and reposition the elements in each iPad view. Time consuming but worth it.
Hope this can be helpful anybody else. I wish when you reconfigured to iPad from iPhone it resized and repositioned the elements in the views but Oh well.

Related

Switching between storyboards/view controllers

So I'm making an iPad app for the very first time and right now I have one view controller with its buttons displayed on the storyboard and everything and what I want to do is when I click on a certain button, it brings me to a new screen.
So I created a second viewcontroller class for the second screen and I created an IB Action method for the button but it's empty because I don't know how to implement it. So what do I have to do to accomplish this?
Try it....
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
// iPad-specific interface here
LBAlertLoginViewController *lbAlertLoginVc = [[LBAlertLoginViewController alloc]initWithNibName:#"LBAlertLoginViewController_iPad" bundle:nil];
[self.navigationController pushViewController:lbAlertLoginVc animated:YES];
[lbAlertLoginVc release];
}
else
{
// iPhone and iPod touch interface here
LBAlertLoginViewController *lbAlertLoginVc = [[LBAlertLoginViewController alloc]initWithNibName:#"LBAlertLoginViewController_iPhone" bundle:nil];
[self.navigationController pushViewController:lbAlertLoginVc animated:YES];
[lbAlertLoginVc release];
}
Hope i helped.

Changing View Controllers - SIGABRT

I am trying to move from one view controller to another when a button is pressed, but it is giving me "sigabrt" error.
This is my code:
-(IBAction)buttonPressed:(id)sender{
StatsViewController *myStats = [self.storyboard instantiateViewControllerWithIdentifier:#"StatsViewController"];
[self presentViewController:myStats animated:YES completion:nil];
}
The only reason i am doing it this way is because i need to pass data forward from one view controller to the next.
I also checked my storyboard there are no connections between the two view controllers (just the above code).
However, when i remove the above code and connect the two view controller using the "control drag" method on the storyboard, it works. no error..
Make sure that the storyboard instance is not nil and and the Storyboard Id is set properly
-(IBAction)buttonPressed:(id)sender{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
StatsViewController *lvc = [storyboard instantiateViewControllerWithIdentifier:#"StatsViewController"];
[self.navigationController pushViewController:lvc animated:YES];
}

Push ViewController on AppDelegate from TabBar Application

I have a Tab Bar application that shows several tabs. I case of notification I want user to be directed to a view controller with the ability to push "Back".
When my app was only Navigation controller app, I used this code in my AppDelegate:
UIStoryboard *mainStoryboard = self.window.rootViewController.storyboard;
DetailViewController *detailViewController = (DetailViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"detailViewController"];
[(UINavigationController*)self.window.rootViewController pushViewController:detailViewController animated:NO];
This code used to work fine until I converted my app to be Tab Bar. Seems like the "self.window.rootViewController" is not longer of type "UINavigationController" and therefore calling "pushViewController" generates an exception saying method doesn't exist.
Any way to make this work on a Tab Bar application?
Thanks
You should present your notification controller as modal (presentViewController:animated:completion:), and inside that controller you provide a way to close it, probably a button on top bar.
EDIT:
Thanks for Dimitry's answer I was able to go on the right track. I just had to make a small trick in order to preserve the top navigation bar and the bottom tool bar. I did it by using a "UINavigationController" instance. Here is the code:
UIStoryboard *mainStoryboard = self.window.rootViewController.storyboard;
DetailViewController *detailViewController = (DetailViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"detailViewController"];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
navigationController.navigationBar.tintColor = [UIColor blackColor];
navigationController.toolbar.tintColor = [UIColor blackColor];
[self.window.rootViewController presentViewController:navigationController animated:YES completion:NULL];

Presenting a Modal View Controller hides the Navigation Bar

I have a navigation based app with a navigation bar, but there are a few instances where instead of pushing a view controller onto the stack, I need to present the view controller modally. The problem is that when I dismiss the modal view controller, everything functions as expected except that the navigation bar is hidden and the (parent view) has been resized, which is the expected behavior according to the docs. So I figured I could simply call a built-in method to unhide the navigation bar. I have already tried
[self.navigationController setNavigationBarHidden:NO];
as well as the animated version without success.
The documentation talks about this in the method
presentModalViewController: animated:
in the discussion section where it says,
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen" and "Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy."However, the docs didn't clue me in as to how to undo this process after dismissing a modal view.
Has anyone else experienced this and found a solution?
Edit: I am having this same problem, so instead of asking my own question I am sponsoring a bounty on this one. This is my specific situation:
In my case, I am presenting an Image Picker in a Modal View Controller, over a Navigation Controller:
-(void) chooseImage {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
imagepicker = [[UIImagePickerController alloc] init];
imagepicker.allowsEditing = NO;
imagepicker.delegate = self;
imagepicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagepicker.navigationBar.opaque = true;
imagepicker.wantsFullScreenLayout = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if (self.view.window != nil) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:imagepicker];
[popoverController presentPopoverFromBarButtonItem:reset permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
} else {}
} else {
[self.navigationController presentModalViewController:imagepicker animated:YES];
}
}
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.popoverController dismissPopoverAnimated:true];
} else {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
//Save the image
}
-(void) imagePickerControllerDidCancel:(UIImagePickerController *)picker {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.popoverController dismissPopoverAnimated:true];
} else {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
}
Make sure you a presenting AND dismissing the modalViewController from the UINavigationController, like so:
// show
[self.navigationController presentModalViewController:vc animated:YES];
// dismiss
[self.navigationController dismissModalViewControllerAnimated:YES];
If your view controller is actually on the UINavigationController's stack then this is the correct way to handle the presentation and dismissal of the modal view controller. If your UINavigationBar is still hidden, there is something else funky going on and we would need to see your code to determine what is happening.
Edit
I copied your code into an app of mine and the UIImagePickerController successfully presented and dismissed and my UINavigationController's UINavigationBar was still there. I truly believe that the problem lays elsewhere in your architecture. If you upload a zip w/ an example project I will take a look.
Simply try following code it will work
SettingsViewController *settings = [[SettingsViewController alloc] init];
UINavigationController *navcont = [[UINavigationController alloc] initWithRootViewController:settings];
[self presentModalViewController:navcont animated:YES];
[settings release];
[navcont release];
One need to present the navigation controller in order to have navigation bar on the presented controller
I think I've seen this behavior when presenting a view controller on the wrong VC. Are you calling presentModalViewController on the navigation controller or the individual VC?
Try calling it from the navigationController if you aren't already.
[self.navigationController presentModalViewController:myVC animated:YES];
If you present a controller as model, View controller will appear to total view.
If you want to access the navigation controller properties over the model view, You need to create another navigation controller reference and it continues as previous.
This may be useful for you.
Check this out. This is Apple's Documentation under UIViewController Class Reference:
It clearly mentions that modal view always presents in full screen mode, so it is obvious that navigation bar will be hidden. So put the seperate navigation bar on modal view to navigate back.
presentModalViewController:animated:
Presents a modal view managed by the given view controller to the user.
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
Parameters
modalViewController
The view controller that manages the modal view.
animated
If YES, animates the view as it’s presented; otherwise, does not.
Discussion
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen. On iPad, the presentation depends on the value in the modalPresentationStyle property.
Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy. The view is animated according to the transition style specified in the modalTransitionStyle property of the controller in the modalViewController parameter.
Availability
Available in iOS 2.0 and later.
Hope this helps you understand that hiding the whole view along with navigation controller is default behaviour for modal view so try putting a seperate navigation bar in modal view to navigate.
You can check it further on this link
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
AddContactVC *addController =[self.storyboard instantiateViewControllerWithIdentifier:#"AddContactVC"];
UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:addController];
[self presentViewController:navigationController animated:YES completion: nil];
working for me shows navigation bar
Emphatic and Devin –
As I started reading through the Apple docs to get familiar with the problem, I noticed that the method you're using, presentModalViewController:animated:, appears to be deprecated in favor of presentViewController:animated:completion:. Perhaps you should try to use that method instead.
For your convenience, take a look for yourself:
presentModalViewController:animated: reference
I'll try to put together a quick test program to see whether what I've said above is actually true. But give it a shot – maybe it'll help!
Xcode has a template that does pretty close to what you're doing. from the results, i don't think you should be attempting to perform [self.navigationController presentModalViewController:vc] and [self.navigationController dismissModalViewControllerAnimated:] , but rather simply [self presentModalViewController:] and [self dismissModalViewControllerAnimated:] .
to see how the template does this for yourself, you can use the new project wizard in xcode 4.3 . perhaps it will provide some guidance:
from that choice, choose Next, then give your test project a name, choose "Universal", turn off automatic reference counting, hit next, save where you want it.
now, click on the target and switch the deployment target to 4.3 (or 4.0 if you prefer) for your testing purposes, and switch to your device or the iOS 4.3 simulator .
finally, substitute the following code in applicationDidFinishLaunching:withOptions: in the created AppDelegate.m:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainViewController_iPhone"
bundle:nil] autorelease];
} else {
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainViewController_iPad"
bundle:nil] autorelease];
}
UINavigationController* navigationController
= [[UINavigationController alloc] initWithRootViewController:self.mainViewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
now, when i run this, it doesn't hide the navigationBar. and in the created MainViewController.m from the template, you'll see how it presents the modal view controller and dismisses it from the controller itself and not from the navigation controller. for good measure, to make the template code more like your own, go into MainViewController.m and delete the line that sets the modal view controller transition style ...
(of course, in iOS 5, with storyboards, the same thing can all be accomplished with modal segues ... which is how i've done this for apps that i'm not supporting for pre-5.0 that present a modalViewController in this fashion.)
One of the best solution it to use this Category MaryPopin
https://github.com/Backelite/MaryPopin

iPad view appears sideways

I am working on an iPad app (which will not be submitted to the App Store) which supports only landscape mode.
Most of the views in the application are pushed onto a UINavigationController with a hidden navigation bar.
When I add the following code in the top view controller in the aforementioned UINavigationController, the new UINavigationController (navController) is created in portrait mode and appears sideways and off-screen.
MyViewController *myViewController = [[MyViewController alloc] initWithNibName:#"MyView" bundle:nil];
// viewController.view is landscape in MyView.xib
// myViewController is created in landscape mode
NSLog(#"%#", NSStringFromCGRect(myViewController.view.frame)); // {{0, 0}, {1024, 704}}
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:myViewController];
// navController is created in portrait mode (why?)
NSLog(#"%#", NSStringFromCGRect(navController.view.frame)); // {{0, 0}, {768, 1024}}
[self presentModalViewController:navController animated:YES];
// navController is shifted off-screen after it is presented modally (why?)
NSLog(#"%#", NSStringFromCGRect(navController.view.frame)); // {{1024, 0}, {748, 1024}}
I cannot find any possible reason for this to occur, nor can I figure out how to reorient the view to landscape mode; I can change its frame but its content is still sideways.
I tried adding the following to MyViewController.m to no avail:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return !UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
I even tried adding this code to a UINavigationController subclass which did not work either.
I was able to get the view navigation controller to orient itself correctly by adding it as a subview of my application's root view.
MyRootViewController *myRootViewController = [[[UIApplication sharedApplication] delegate] myRootViewController];
[myRootViewController presentModalViewController:navController animated:YES];
This code is in the top view controller of the navigation controller which is a subview of the root view.
Not sure if this will work, but you could add this key to your Info.plist to indicate what orientation your app supports (at least, this will prevent it from starting in portrait):
UISupportedInterfaceOrientations~ipad => (UIInterfaceOrientationLandscapeLeft, UIInterfaceOrientationLandscapeRight)