Switch between view controllers - objective-c

I want programatically switch from one view controller to another. I use the following code :
SenderPlayerViewController *myViewController = [[SenderPlayerViewController alloc] init];
[self.navigationController pushViewController:myViewController animated:YES];
but I get a black screen, while I have already put some controls in SenderPlayerViewController.

Are u trying to instantiate with an nib file? If so, you must use initWithNibName:bundle:
SenderPlayerViewController *myViewController = [[SenderPlayerViewController alloc] initWithNibName:#"SenderPlayerViewController" bundle:nil];
Also with a story board it is not enough to call alloc init on a controller class.
It should be something like
UIViewController *viewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:#"SenderPlayerViewController"];

If you are using a view controller from a storyboard you should use
SenderPlayerViewController *myViewController=[storyboard instantiateViewControllerWithIdentifier:#"TheNameOfYourController"]
instead of alloc init.

Related

PresentModalViewController not showing TabBar

I'm trying to go from one xib to another and I'm using TabBar.
When I move from xib to xib with PresentModalViewController I lose the TabBar.
When I use this way, it fail (like force close in android):
FirstViewController *fvc = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
[fvc setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
fvc.userSelectedLatitude = saveLatitude;
fvc.userSelectedLongitude = saveLongtitude;
UITabBarController *tabControl = [[UITabBarController alloc] initWithNibName:fvc bundle:nil];
[self presentModalViewController:tabControl animated:NO];
When I use:
UITabBarController *tabControl = [[UITabBarController alloc] initWithNibName:#"FirstViewController" bundle:nil];
I get black screen with TabBar.
Since it all fail I guess it is not the right way.
So, what is the right way to do it?
The code above crashes because you are trying to pass a view controller instead of an NSString object in the initWithNibName:bundle: method.
The way to do it depends of what you really want to do. Do you want to present the xib in a modalViewController with or without a tabBar?, or simply present the view controller modally?.
UPDATE:
Fine, you have to create first your view controllers associated to each tabBar button (like you have been doing until now), after, add these view controllers to your tabBar and then present the tabBarController modally. Like this:
FirstViewController *fvc = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
fvc.userSelectedLatitude = saveLatitude;
fvc.userSelectedLongitude = saveLongtitude;
UITabBarController *tabControl = [[UITabBarController alloc] init];
[tabControl setViewControllers:[NSArray arrayWithObjects:fvc, nil]];
[tabControl setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentModalViewController:tabControl animated:NO];
I think this code should work. So, try it and tell us if something goes wrong.
With UITabBarController, there is no need to manually present viewControllers or call code to switch the views. This is handled for you.
All you need to do is set the viewControllers property of the UITabBarController. Like so:
[tabBarController setViewControllers:[NSArray arrayWithObjects:view1, view2, nil]];

Can I Show A SplitViewController Using presentModalViewController?

I don't know if what I'm trying to do is possible, but because I haven't the desired results, I guess not.
What I'm trying and need to do is to call a SplitViewController from a previous ViewController, using presentViewController.
I know, SplitViewController have to be the rootViewController, but I need to explore the most possible options to achieve what I need to do.
I have a MainMenu with buttons, and with every button, I need to call a SplitViewController. First, how can do this?
What I'm trying to do is this:
First, in AppDelegate I'm calling the MainMenu, and add as a subview and other things:
-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[window addSubview:self.mainMenu.view];
[self.mainMenu presentModalViewController:self.firstMenu animated:NO];
[self.window makeKeyAndVisible];
return YES;
}
Then, in the MainMenu, I'm calling SecondViewController, in modal view, using this code:
SecondViewController *secV = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
secV.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:secV animated:YES];
In this SecondViewController, I'm creating SplitViewController, with Master & DetailViewController's, using this code:
-(void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UISplitViewController *splitViewController = [[UISplitViewController alloc]init];
SecondMenuViewController *secMenu = [[SecondMenuViewController alloc]init];
UINavigationController *navLef = [[UINavigationController alloc]init];
[navLef pushViewController:secMenu animated:NO];
SecondMainViewController *secMain = [[SecondMainViewController alloc]init];
UINavigationController *navRig = [[UINavigationController alloc]init];
[navRig pushViewController:secMain animated:NO];
splitViewController.delegate = secMain;
splitViewController.viewControllers = [NSArray arrayWithObjects:navLef, navRig, nil];
MainAppDelegate *mainApp = [[MainAppDelegate alloc]init];
[mainApp changeRootViewController:splitViewController];
navRig = nil;
navLef = nil;
secMain = nil;
secMenu = nil;
splitViewController = nil;
}
As you can see, I'm calling a method in MainAppDelegate, to change view and RootViewController, because SplitViewController have to be RootViewController. This is the method:
-(void)changeRootViewController:(UISplitViewController *)splitViewController{
[self.window addSubview:splitViewController.view];
self.window.rootViewController = splitViewController;
}
I know, this looks like a mess. And when I run, the SplitViewController never shows, so I assume, what I'm trying to do is not possible? Or In what I'm wrong?
If it is everything, what can I do to show a SplitViewController after my MainViewController?
I'm using XCode4.4 and iOS5
Thank you very much
A better way would be to make your UISplitViewController the root view controller in application:didFinishLaunchingWithOptions:. Then present your MainMenu on top of it. You can change the subviews displayed by the split view controller to correspond to what button the user pushes in your MainMenu.
First, didFinishLaunchingWithOptions: is too early to be calling presentModalViewController. You haven't even got an interface yet!
Second, you don't seem to have a root view controller (although perhaps you're getting one from a nib? you should probably stop doing that; use the techniques shown in the current application templates).
Third, note that now that we have custom container views, there is no need for you to use UISplitViewController at all; you can construct your own view / view controller hierarchy, and you might be happier doing so, since UISplitViewController is not a very well-constructed class.

Call storyboard scene programmatically (without needing segue)?

I have a modal storyboard scene that I want to be accessible to all my other scenes. Creating a modal segue to it from every scene on my storyboard creates a big mess of strings going everywhere. Is there a way that I leave off the segues and call the scene programmatically instead?
Basically I want to do something like this:
MyNewViewController *myNewVC = [[MyNewViewController alloc] init];
[self presentModalViewController:myNewVC animated:YES];
except instead of creating and pushing a view controller class, I want to do a modal transition to an "isolated" (not connected with a segue) storyboard scene.
Yes you can. Do something like this to get access to the VC, then just Modal Push it:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
MyNewViewController *myVC = (MyNewViewController *)[storyboard instantiateViewControllerWithIdentifier:#"myViewCont"];
Note: the method presentModalViewController:animated is deprecated in iOS 6.
The new code should read:
NSString * storyboardName = #"MainStoryboard_iPhone";
NSString * viewControllerID = #"ViewID";
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
MyViewController * controller = (MyViewController *)[storyboard instantiateViewControllerWithIdentifier:viewControllerID];
[self presentViewController:controller animated:YES completion:nil];
In the storyboard give your view controller an identifier (under the Attributes Inspector) then use the following code to bring that view forward.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"STORYBOARDNAME" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"VIEWCONTROLLERIDENTIFIER"];
[self presentModalViewController:vc animated:YES];
I have a case where I want to present a view controller from the main part of the app, one with settings & help & so on. To do this, I want it to be within a nav controller, sort of a little plug in module we can call from a UIBarButtonItem.
Now, this can be to/in the current storyboard, or to another, it doesn't matter.
I want to do it this way, because I loathe the potential of segue line spaghetti all over my storyboard.
Here's how to do it.
- (IBAction)displaySettings:(id)sender
{
LOG_SELECTOR() // google that for extra goodness
// FYI, this can be done using a different storyboard like so.
/*
NSString * storyboardName = #"MainStoryboard_iPhone"; // possibly use device idiom?
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
*/
// To push a new set of scenes with a new Navigation Controller, it is done like this:
UINavigationController *settingsNC = [self.storyboard instantiateViewControllerWithIdentifier:#"Settings Nav Controller"];
OBSettingsUIViewController *settingsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"Settings root"];
[settingsNC pushViewController:settingsVC animated:NO];
[settingsNC setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
// Present the view controller;
[self presentViewController:settingsNC animated:YES completion:NULL];
}
In the presented view controllers (or in a subclass of the Navigation Controller), you can have a UIBarButtonItem to then dismiss the whole presented hierarchy of view controllers like so:
- (IBAction)dismissThisVC:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Hope this helps a bunch of people out. Cheers.
Just call viewcontroller using navigation controller
Write this code in viewcontroller and set viewcontroller in storyboard as set in the image.
ProfileVC *vc = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"ProfileVC"];
[self.navigationController pushViewController:vc animated:YES];
Call to navigate to other class
UIWindow *window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UINavigationController *navController = (UINavigationController *)window.rootViewController;
DumpFeed *dump = [storyboard instantiateViewControllerWithIdentifier:#"DumpFeed"];
dump.isPushed=YES;
dump.strUserId = appDelegate.strFriendid;
[navController pushViewController:dump animated:YES];
Heres a Swift version of this:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myVC = storyboard.instantiateViewControllerWithIdentifier("myStoryId")
self.presentViewController(myVC, animated: true, completion: nil)
You should also change your storyboard id like this:
I think that with iOS7 it has become very easy implementing via the storyboard
I'm currently learning about the new features in iOS7 and found this simple solution, but it might have been relevant even in prior versions, I'm not sure.
First u need to connect the presenting VC with the target VC (thats the only connection needed), then within the storyboard's attributes inspector choose the style to be modal, in the identity inspector give your VC a storyboardID and make sure you checked the 'use storyboardID' checkbox,
If its not there yet add this method to your presentingVC:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
YourTargetVC * targetVC =
(YourTargetVC *)segue.destinationViewController;
if(nil != targetVC) {
//Do preparations here
}
}
Now, when you wish to show your targetVC from your presentingVC you can use:
[self performSegueWithIdentifier:(NSString *) sender:(id)];
where the identifier is your viewController's storyboardID, and the sender is the view who triggered the action, this method will invoke the storyboards scene, so the [prepareForSegue: sender:] method will be called allowing u making last modifications before the targetViewController will appear.

How to remove multiple many view from superview

I have some uiview, one call another in this way:
From first uiview:
MyViewController *contr1 = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[self.view addSubview:contr1.view];
From second uiview:
MyViewController2 *contr2 = [[MyViewController2 alloc] initWithNibName:#"MyViewController2" bundle:nil];
[self.view addSubview:contr2.view];
now in the third uiview i want to return back on the first updating it ( calling viewDidLoad ). how can i do?
First of all - you are doing it wrong.
Since you are using view controllers present them modally or push them:
MyViewController2 *contr2 = [[MyViewController2 alloc] initWithNibName:#"MyViewController2" bundle:nil];
[self presentModalViewController:contr2];
If you want to dismiss modal controllers exactly to your root view controller you should obtain a pointer to it in the controller you are currently using and send it a message to dismiss every modal view that there is on it.
- (IBAction)doHomePage:(id)sender {
MyAppDelegate *appDelegate = (MyAppDelegate *)[UIApplication sharedApplication].delegate;
[appDelegate.navigationController.rootViewController dismissModalViewControllerAnimated:YES];
}
Also instead of viewDidLoad: you might want to use viewWillAppear: or viewDidAppear:.
Sorry beforehand if there are some typo errors in the code since I wrote it by hand.

adding subview of another class

iv created a class with xib so i can access it throughout my app. The class basically holds a nib with has three uiviews and a few buttons buttons+labels. Now im calling class A (the one with 3 view etc) from classB but every time i addsubview to self.view nothing happens. any help appreciated.
ive done the following in class B.h
#import "PlayResultViewController.h"
PlayResultViewController *playResultViewController;
in classB.m
//viewdidload
playResultViewController = [[PlayResultViewController alloc]init];
//some random method
[placeholderView addSubview:playResultViewController.loseView];
You are missing the initWithNibName to start with, here are some examples
With a Navigation controller u can use
BViewController *bController = [[BViewController alloc] initWithNibName:#"BViewController" bundle:nil];
[self.navigationController pushViewController:bController animated:YES];
[bController release];
without UInavigation controller you can test with
BViewController *bController = [[BViewController alloc] initWithNibName:#"BViewController" bundle:nil];
self.view = bController;
// or alternatively self.view = bController.view;
[bController release];
You need to tell it which nib to load....
playResultViewController = [[PlayResultViewController alloc] initWithNibName:#"Mynib" bundle:nil];