I have a split-view app that allows a user to select and display a thumbnail of a chosen image. I have placed a UIButton in the detailViewController using Interface Builder. When this button is pressed, I would like to have it change to a full screen view of the image. I have set up a new View Controller, called FullViewController and thought I had everything connected. The problem is that the navigation controller is null. I adjusted the AppDelegate.m to the following:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch.
// Set the split view controller as the window's root view controller and display.
self.window.rootViewController = self.splitViewController;
UINavigationController *nvcontrol =[[UINavigationController alloc] initWithRootViewController:fullViewController];
[window addSubview:nvcontrol.view];
[self.window makeKeyAndVisible];
return YES;
}
This is the function in the DetailViewController.m which is called when the button is pressed. The navigation controller comes up null in here.
//Function called when button is pressed - should bring up full screen view
- (IBAction) pressFullViewButtonFunction: (id) sender{
//viewLabel.text = #"Full View";
if (fullViewController == nil){
FullViewController *fullViewController = [[FullViewController alloc] initWithNibName:#"FullViewController" bundle:[NSBundle mainBundle]];
NSLog(#"fullViewController is %#", fullViewController);
self.fullViewController = fullViewController;
}
NSLog(#"self.navigationController is %#",self.navigationController);//this is null
[self.navigationController pushViewController:self.fullViewController animated:YES];
}
I'm not sure how to fix this. I've tried adding in the couple lines in the AppDelegate, but when it runs, the table in the root view doesn't show up and it no longer properly switches between portrait and landscape views.
I have the rest of the code readily available if that would help clarify. Just let me know!
Thanks.
From the code you post it is not possible to identify the problem, but two common reasons for self.navigationController to be nil are:
you did not push the object behind self on to the navigation controller in the first place; indeed it seems so, since the navigation controller is added as a subview of the split view controller; possibly you mean the opposite... not sure...
(sub-case of 1) you showed the object behind self using presentViewControllerModally.
When I say "the object behind self" I mean the instance of the class where pressFullViewButtonFunction is defined.
If you need more help, post the code where you push your controllers on to the navigation controller...
On a side note, if you do:
UINavigationController *nvcontrol =[[UINavigationController alloc] initWithRootViewController:fullViewController];
and nvcontrol is not an ivar, then you have a leak.
Hope this helps...
Related
I am using multiple viewcontrollers but need to change which who loads first. I have found some old tips but those are regarding .nib files and I belive those might not be up to date. Preferably I'd like to find some option in the menu's, as I frankly think this should be very simple.
Any ideas to a simple way of changing with viewController is loaded first?
Open the storyboard file
Display the document outline
Select the view controller that you want to be first
Under the "Attributes inspector", select "Is Initial View Controller"
You can programmatically load a view controller first through your AppDelegate.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.rootViewContoller = <firstViewControllerIWantToLaunch>;
return YES;
}
This ensures that the view controller you want to load first is the root view controller, and will be the first view controller presented.
If you're using storyboard, select the view controller you'd like, and search for the "Is initial view controller" checkbox. I can't tell you where exactly it is, since I don't have Xcode open.
If you're using xibs, you need to change it in the AppDelegate applicationDidFinishLaunchingWithOptions method. (Refer to Bryan's answer for that.
If you want to switch between the two view controllers programmatically, Try doing Some thing Like this,
In your AppDelegate.m file in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions.. Method
just place this condition..
If(loadFirstView){
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
FirstViewController *menu = [navController.storyboard instantiateViewControllerWithIdentifier:#"FIrstVC"];
navController.viewControllers = [NSArray arrayWithObjects:menu, nil];
[self.window makeKeyAndVisible];
}else{
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
SecondViewController *menu = [navController.storyboard instantiateViewControllerWithIdentifier:#"SecondVC"];
navController.viewControllers = [NSArray arrayWithObjects:menu, nil];
[self.window makeKeyAndVisible];
}
Don't Forget to assign StoryboardIDentifiers "FirstVC" and "SecondVC" in your storyboard fileā¦This should do it, It works Well for me
As already answered here, you need to select your project's main storyboard file, select the main view controller, go to attributes inspector and, check the checkbox title "Is Initial View Controller" to make main view controller loading as first view controller upon app launch.
I have a main view controller using a navigation controller and i was making my application over that. Now i want to add a welcome view controller for my app and make it show first instead of my main view controller. Is there any way to do it.
What I did was adding a view controller to my storyboard and added two classes of the same name then i made it my root view controller and unchecked the root view controller from the main view but it is not showing on the window. Please help me, that how can i make my welcome view to appear before the main view controller. Thanks
Inside Interface Builder, under the attributes section (looks like a small slider) about a quarter of the way down the list of settings, there is a section labeled "View Controller." The second item in that section is a checkbox "Is Initial View Controller," check that box and you should see the starting arrow of the story board move to the specified view controller and the app should launch to that page.
Hope this Helps.
You could do this programmatically by setting the app window's rootViewController. From the app delegate's application:didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIScreen *mainScreen = [UIScreen mainScreen];
self.window = [[KTAppWindow alloc] initWithFrame:mainScreen.bounds];
[window makeKeyAndVisible];
window.rootViewController = [[WelcomeViewController alloc] init];
return YES;
}
Then you just need to set up your trigger to switch from the Welcome view to the main view. This could be scheduling an NSTimer, for example. Whatever the trigger is, once it occurs just change the window's rootViewController instance to your MainViewController.
I hope this helps.
It calls "Splash Screen" you just need to add a new ViewController in your Storyboard or if you don't have a Navigation Controller add.
In the Splash class, in the viewDidLoad method you need to put this:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
HomeViewController *vc = [sb instantiateViewControllerWithIdentifier:#"Home"];
[[[[UIApplication sharedApplication] delegate] window] setRootViewController:vc];
[self performSegueWithIdentifier:#"Home" sender:self];
here you can add conditions if you needed
So I'm trying to convert a single view application into a tabbed application. My use case is this - in one of the view controllers I want to push a new view controller and still have the tab underneath.
I'm currently doing this -
[self.tabBarController setViewControllers:#[self.searchViewController, self.loginViewController]];
[self.searchViewController presentViewController:self.searchViewController.detailController animated:YES completion:nil];
However, this makes the tab across the bottom disappear.
What should I do?
presentViewController is a "modal" presentation - the presented view controller takes over the entire screen. If you want to remain within the tab but move between view controllers, the root view controller in the tab should be a UINavigationController. You can then push/pop view controllers onto that.
There are two primary methods for view navigation, the first is a presentation which displays a view from the bottom that slides up, and the second is a push which displays a view from the right that slides in from the side.
In most cases, the view I am going to display and what action kicked off the navigation determine which method I will use. For example, if I have a table view that has a list of music albums and I want to search for a song by a particular artist, to see the songs within that album I want to PUSH the view controller, i.e. slide to the right. This gives me the built-in (and intuitive) ability to go back via the automatically added back button on the navigation bar in case the song I was looking for wasn't in the album I selected.
If perhaps I wanted to present the user with the ability to edit the album details, such as renaming the album, this is a totally different type of action, and I would want to PRESENT such a view modally, i.e. from the bottom.
The major distinction between the two is where are you going and what are you doing. If the next view you are going to show is something that does one action and you are then returned back to the original view, presenting modally from the bottom is conventional. If you are doing to be potentially navigation further and further into subsections and will be coming back and forth between said subsections, like Artist->Album->Song etc., you are going to want to push the view from the side, just like the default music app in iOS does.
This is an example starter project I created that demonstrates an easy way to make this work the way you likely want. I create instances of the different view controllers I want to be contained in the tabBarController, which are associated with the tabs, and then "wrap" them each with their own navigation controller before adding them to the tabBar via the .items property. This way each view controller has its own navigation hierarchy and within each you'll be able to call [self.navigationController pushViewController:] or [self.navigationController presentViewController] to keep the navigation 'within' the views and separate from the tabBar itself.
#import "AppDelegate.h"
#import "TabBarViewController.h"
#import "InfoViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
InfoViewController *firstVC = [[InfoViewController alloc] init];
firstVC.title = #"First";
firstVC.view.backgroundColor = [UIColor redColor];
UINavigationController *firstNC = [[UINavigationController alloc] initWithRootViewController:firstVC];
InfoViewController *secondVC = [[InfoViewController alloc] init];
secondVC.title = #"Second";
secondVC.view.backgroundColor = [UIColor blueColor];
UINavigationController *secondNC = [[UINavigationController alloc] initWithRootViewController:secondVC];
TabBarViewController *tabBarVC = [[TabBarViewController alloc] init];
tabBarVC.viewControllers = #[firstNC, secondNC];
self.window.rootViewController = tabBarVC;
[self.window makeKeyAndVisible];
return YES;
}
That resulted in the following:
Hope that helps!
I am a beginner iPhone developer so I apologise if there is a lack of information here. I have created a storyboard which has an initial view controller (for app login) and if I detect that there is already a user logged in (I have an API token for a user stored already) then I will load a navigation controller instead which has a root view controller defined which is a table view controller. Within the table view controller I have a navigation item which contains left and right bar button items. I added another view controller with a label on, then I ctrl dragged from the right navigation bar button item to the simple view controller to create a segue. This segue is the one which does not work when I build and run the app. I also tried to create an IBAction and hook that up to the right bar button item and NSLog "Hello world" but that doesn't work. Here is how I am initialising the storyboard:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Instantiate the UIStoryBoard
UIStoryboard *initiialStoryBoard = [UIStoryboard storyboardWithName:#"iPhoneStoryboard" bundle:nil];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
// Set the first view controller of the storyboard as the root controller.
User *user = [[User alloc] init];
if ([user token] == nil) {
[self.window setRootViewController: [initiialStoryBoard instantiateInitialViewController]];
} else {
UINavigationController *feedNavigationController = [initiialStoryBoard instantiateViewControllerWithIdentifier:#"feedNavigationController"];
[self.window setRootViewController:feedNavigationController];
}
[self.window makeKeyAndVisible];
}
Can anyone suggest what I could be doing wrong?
First, remove all your code within the method application:didFinishLaunchingWithOptions: and just return YES;.
Create your storyboard like in the image below.
Use a UINavigationController as your entry point.
Set your authentication view controller as the rootViewController of the UINavigationController
Use another segue from your authentication view controller to your feed view controller and give it the segue identifier segueFeed
After that add the following code to your authentication view controller:
- (void) awakeFromNib
{
// Set the first view controller of the storyboard as the root controller.
User *user = [[User alloc] init];
if ([user token] == nil)
{
// do nothing because the correct view controller will be shown
}
else
{
// show the feed view controller
[self performSegueWithIdentifier:#"segueFeed" sender:nil];
}
}
Now the authentication view controller will be shown automatically if no token is given and otherwise the feed view controller will be shown immediately. At this point you can add your own navigation items (like Action 1 and Action 2) and connect them with other view controllers via segues.
I have created single view iOS application with some basic functionality. and added the table view in simple view controller now I wanted to use table view with row navigation like(pushcontroller and popcontroller) is that possible and if it is, how we can set that.
If you need full support for push/pop operation, I would use a navigation controller.
On the other hand, you could simply present your detail view controllers when a table row is tapped:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MyViewController* detailController = <CREATE THE VIEW CONTROLLER>;
[self presentViewController:detailController animated:YES completion:NULL];
}
In this case, your detailController will need to implement a sort of navigation bar or other mechanism to let the user dismiss the controller (through dismissViewControllerAnimated:completion:) and go back to the table view. (Using a navigation controller would instead take care of this in a canonical way.)
One major drawback of the simpler solution based on presenting/dismissing is the fact that all the view controllers presented this way are dismissed at once, so you cannot have multiple levels of navigation.
EDIT:
To add a navigation controller to your app, simply do something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
MyViewController *myViewController = [[MyViewController alloc] initWithNibName:nil bundle:nil];
...
self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = self.navigationController;
[self.navigationController pushViewController:myViewController animated:YES];
...
[self.window makeKeyAndVisible];
return YES;
}
At the moment, your didFinishLaunchingWithOptions method should use the addSubview method to make your main view controller (named MyViewController in my example) visible. You can replace that call by the code above to instantiate the navigation controller and push on to it your main view controller.
Alternatively, you could create a new Xcode project using the navigation-based template and move all of your source files over.