I am trying to implement a modal navigation controller as described in the Apple iOs Guide: Combined View Controller Interfaces
I have come to the conclusion that I am missing something both obvious and stupid as I simply cannot get anything to display, I get a blank white screen.
Swapping things out I can prove that the view controller that I am using as the navigation controllers RootViewController works fine on it's own (by adding it manually as a view subChild).
Further, implementing addSubView ([self.view addSubview:navController.view]) instead of presentModalViewController seems to work OK.
Can anyone point out my simple error because I am 5 minutes short of kicking my own face :D
header
#import <UIKit/UIKit.h>
#interface BaseViewController : UIViewController {
}
implementation
#import "BaseViewController.h"
#import "ScannedListViewController.h"
#import "ScannedItemViewController.h"
#implementation BaseViewController
- (void)viewDidLoad {
ScannedListViewController *listViewController = [[ScannedListViewController alloc] init];
ScannedItemViewController *itemViewController = [[ScannedItemViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:listViewController];
[navController pushViewController:itemViewController animated:NO];
[self presentModalViewController:navController animated:YES];
[listViewController release];
[itemViewController release];
[navController release];
[super viewDidLoad];
}
The RootControllerView is a basic test TableViewController with the following header
#interface ScannedListViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>
Thank you in advance if your able to help
Why are you presenting something modally in a view controller's viewDidLoad method? I find that odd off the top. Generally you show a modal view controller in response to some action (like tapping a button).
Is there a reason you're showing a navigation controller with a second view controller already pushed on it after the root?
You should have [super viewDidLoad] as the first line, not the last line, of the method.
You do not need to have <UITableViewDelegate, UITableViewDataSource> after UITableViewController because it already adopts those protocols. Remove that bit.
Related
My app currently has a UINavigationController and I'd like to push a UITabBarController at some point when a button is clicked. I am trying to create it on Interface Builder (as opposed to programatically).
All online tutorials show how to create a tab bar based app, which involves dragging a UITabBarController into the MainWindow.xib which is obviously not what I want.
What I did was create a UIViewController, and its nib file, dragged a UITabBarController. Now pushing that UIViewController to the navigation controller will show an empty view (its empty view). Removing the view in the view controller will crash the app. How can I tell the UIViewController to load a UITabBarController instead of its own view?
For those down-voting me: it would be decent to at least provide a comment. The question is not a poor question. The questions is asking for suggestions for how to use a UITabBarController in an unorthodox way. I tried most of the suggestions and they do not work. If you are down-voting, at least write a comment.
You can see this this may help you
Since this is how you want your app to be: - Navigation Controller - Root View Controller - Other View Controllers - Tab Bar Controller - First VC under tab - Second VC under tab - Third VC under tab - more view controllers
in your view controller where you want to pushViewController to UITabBarController use this
//create a UITabBarController object
UITabBarController *tabBarController=[[UITabBarController alloc]init];
//FirstViewController and SecondViewController are the view controllers you want on your UITabBarController (Number of view controllers can be according to your need)
FirstViewController *firstViewController=[[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *secondViewController=[[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
//adding view controllers to your tabBarController bundling them in an array
tabBarController.viewControllers=[NSArray arrayWithObjects:firstViewController,secondViewController, nil];
//navigating to the UITabBarController that you created
[self.navigationController pushViewController:tabBarController animated:YES];
This tutorial might help. It comes with an example code.
Hi just make both nav controller and tabBar Controller in app delegate.
Initially add navController to your root view..
[self.window addSubview:navigationController.view];
and whenever you want to add tab bar then remove navController and add tabBarController.
-(void)addTabBarController
{
AppDelegate *appdelegte =(AppDelegate*)[[UIApplication sharedApplication]delegate];
[[[appdelegte navigationController] view]removeFromSuperview];
[[appdelegte window]addSubview:[[appdelegte tabcontroller]view]];
[[appdelegte tabcontroller]setSelectedIndex:0];
}
If you get any problem then ask me again..
In YourView controller make IBOutlet of tabBarController
in .h file
#import <UIKit/UIKit.h>
#interface YourView : UIViewController
{
IBOutlet UITabBarController *tabBarController;
}
-(IBAction)loadTabBar:(id)sender;
#end
and in .m file
#import "YourView.h"
#import "FirstViewController.h"
#import "SecondViewController.h"
#implementation YourView
-(IBAction)loadTabBar:(id)sender
{
FirstViewController *firstView = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:firstView, secondView, nil];
[self.navigationController pushViewController:tabBarController animated:YES];
}
#end
The tabBarController IBOutlet must be connected to the UITabBarController that on the .xib file. And that UITabBarController with two view controllers named FirstViewController, SecondViewController.
I remember doing something similar to this...
I had to create a custom UITableViewController to do this, if you are going to use UINavigationController to 'push' to it.
Doing it only in interface builder may be a bit tricky, it's been a while since I've been at it, I do recall it was a bit of a nightmare to get going correctly.
The problem was, as I believe I've mentioned somewhere, is that the XIB does not have a UIView connected to it. When the UIView is deleted in a XIB file and a UITabBarController is added, the view property of the XIB has to be connected to the UITabBarController's view. I connected it and it worked. That was the reason why I was getting a SIGTRAP.
take a uiview of tab bar controller means create an interface builder with tabs and add that tab bar uivew in your classes where ever u wanted the tab bar
for example take a tab bar uiview of 3 tabs in that uiview take the three buttons in the interface builder
for every navigation of that classu should add this uiview class
-(IBAction)firt_button_pressed:(id)sender
{
}
-(IBAction)second_button_pressed:(id)sender
{
}
All I need is to view a UIView controller in same storyboard file manually with code. I use storyboard to make all forms and connections. My application starts in navigation controller, which provides me access to UIView (LoginViewController) and then it goes to tab bar controller, which provides 4 UIViews. According to every UIView I have .h and .m files. I know about segue method, it is simple, but I need manual method. Maybe I am doing something wrong.
I was trying to use this method for pushing view controller in IBAction:
[self.view pushViewController:LoginViewController animated:YES];
But it makes an error:
Unexpected interface name ‘LoginViewController’: expected expression
It took a lot of time to figure out what is wrong, but I had not succeed.
Here is my RollEnemyController.m file:
// RollEnemyController.m
#import "RollEnemyController.h"
#import "LoginViewController.h"
#implementation RollEnemyController;
#synthesize AttackButtonPressed;
- (IBAction)AttackButtonPressed:(id)sender {
LoginViewController* controller = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[self.view pushViewController:controller];
}
#end
And this is header file:
// RollEnemyController.h
#import <UIKit/UIKit.h>
#interface RollEnemyController : UIViewController
- (IBAction)RollButtonPressed:(id)sender;
#property (weak, nonatomic) IBOutlet UIButton *AttackButtonPressed;
#end
I'm guessing that you are using a UINavigationController. Then you can simply do like this:
LoginViewController *controller = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
Update:
If you are using a UIStoryboard, you can set the identifier of your new viewcontroller, and then push it onto your navigationController. To set the identifier, choose your view, open the Attributes Inspector, and set the identifier ("LoginIdentifier" in my example). Then you can do this:
LoginViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"LoginIdentifier"];
[self.navigationController pushViewController:controller animated:YES];
As a sidenote, I see that you are using capital characters for your methods. You should probably try to avoid that, and instead use lowered first-characters in your method names. And since you say you are learning Objective-C, you should check out this awesome thread here on SO: link.
Update 2:
Here is a zip file with a project showing how to do this. :-)
hello try to use this code
Storyboard put ID = "xxx * Name Desire"
mark use StoryboarID
UIStoryboard * storyboard = self.storyboard;
DetailViewController * detail = [storyboard instantiateViewControllerWithIdentifier: # "xxx * Name Desire"];
[self.navigationController pushViewController: detail animated: YES];
In this statement:
[self.view pushViewController:LoginViewController animated:YES];
it seems you are trying to push a class. You should push an object, your actual controller:
LoginViewController* controller = [[LoginViewController alloc] init...];
[self.view pushViewController:controller animated:YES];
this will at least compile, and if all the rest is fine, also give you the second controller.
EDIT:
I missed one point. You are pushing the view controller on to a view. That makes no sense, you should push the controller on to the navigation controller:
<AppDelegate> *del = (AppDelegate*)[UIApplication sharedApplication].delegate;
[del.navigationController pushViewController:controller animated:YES];
This is true, at least, if you created your project from the Navigation-based template (which creates an application delegate with a reference to the navigation controller). Otherwise, please provide details about how you create the navigation controller.
You mentioned in a comment that you're using UIStoryboard. Are you aware of UIStoryboardSegue? All you have to do it control-drag from the button to the next view controller to establish a segue. Then you can choose the type of transition. Be aware that your view controllers need to be part of a UINavigationController in the storyboard to perform a "Push" animation.
I have created a new application using the View Based Application Template in xCode.
My first view, which displays on loading the app, is a button based menu. One of the buttons (Make) should load a new navigation stack using a NavigationViewController. There are other buttons that when implemented will do other things outside of NavigationViewController's scope.
I would like to be able to click Make and open and display a new navigation controller.
From ViewController.m:
-(IBAction)makeStory:(id)sender{
NSLog(#"makeStory:");
navController = [[UINavigationController alloc] init];
makeStoryTableViewController = [[MakeStoryTableViewController alloc] initWithNibName:#"MakeStoryTableViewController" bundle:nil];
[navController pushViewController:makeStoryTableViewController animated:YES];
}
I have created a NavigationViewController in the opening ViewController.h file:
#import <UIKit/UIKit.h>
#import "MakeStoryTableViewController.h"
#interface StoryBotViewController : UIViewController {
UINavigationController *navController;
MakeStoryTableViewController *makeStoryTableViewController;
}
- (IBAction)makeStory:(id)sender;
#end
I know I'm missing something because when I call pushViewController nothing happens - I think that somehow I have to attach the NavigationViewController to the ViewController that makeStory: is in.
For reference, my app delegate header declares the view controller in the #implementation as follows:
UIWindow *window;
StoryBotViewController *viewController;
with the appropriate #synthesize in the .m of the app delegate
#synthesize window;
#synthesize viewController;
How do I push a NavigationStack on from my opening view controller?
Please forgive me if the question is a little vague, I'm happy to provide more information if you need it. It's my first time questioning on stackoverflow and I'm obviously a bit of a newbie with the iPhone SDK.
you had it almost. But you forgot to add the NavigationController to your view.
[self.view addSubview:navController.view];
Add this in your IBAction.
EDIT:
but much likely this is not what you want, because you can't navigate back to your very first viewController. If you want to navigate back to the first viewController set up your project like in the navigation-based template. You can to this programmatically to:
Move all UINavigationController stuff from the header file of the viewcontroller to the app delegate header. And change your app delegate implementation to something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
navController = [[UINavigationController alloc] initWithRootViewController:viewController];
// Add the view controller's view to the window and display.
// [window addSubview:viewController.view];
[window addSubview:navController.view];
[window makeKeyAndVisible];
return YES;
}
make sure to release navController in dealloc
then replace your IBAction with something like this:
- (IBAction)makeStory:(id)sender {
makeStoryTableViewController = [[MakeStoryTableViewController alloc] initWithNibName:#"MakeStoryTableViewController" bundle:nil];
[self.navigationController pushViewController:makeStoryTableViewController animated:YES];
}
if you don't like to display the navigationbar in your first viewcontroller hide it, but make sure to unhide it if you push other items on the stack. self.navigationController.navigationBar.hidden = ...
im newbie developer and creating my first iphone app... and i have one little problem :)
i switching in my program 2 views, secondView is over firstView, and when i press 2 times or more on button to show the SecondView iphone simulator stopping worling and if after i press to show the FirstView he still showing SecondView view :(...
and i need help how to make button to pressing one time only, and if after switch back to FirstView to can again press one time,and shows like presse,now it show pressed only when i tuch it,... i want like buttons in TabBar, and if i use the TabBar is more harder for me i dont know how to resize it to height and add custom background, and change the effect of pushed button
Thanks you very much and sorry for my bad english!.
here is what code i use to switching views with buttons
// FirstView.h
#import <UIKit/UIKit.h>
#interface FirstView : UIViewController {
}
-(IBAction) goToSecondView:(id) sender;
-(IBAction) goToFirstView:(id) sender;
#end
// FirstView.m
#import "FirstView.h"
#import "SecondView.h"
#implementation FirstView
SecondView *secondView;
-(IBAction) goToSecondView:(id) sender{
secondView = [[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
[self.view addSubview:secondView.view];
}
-(IBAction) goToFirstView:(id) sender {
[secondView.view removeFromSuperview];
}
thank you very much!
This:
#implementation FirstView
SecondView *secondView;
... is most likely the source of your crash. You shouldn't define instance variables in the implementation. The compiler may allow it but the runtime will be confused and the instance variable will not be properly retained.
You should define it like:
#interface FirstView : UIViewController {
SecondView *secondView;
}
#property(nonatomic, retain) SecondView *secondView;
...and use it like:
-(IBAction) goToSecondView:(id) sender{
UIView *newView = [[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
self.secondView=newView;
[newView release];
[self.view addSubview:self.secondView.view];
}
For clarity you should also rename FirstView and SecondView to FirstViewController and SecondViewController because they are view controllers and not views themselves.
More generally, what you are trying to do is dangerous and difficult. You don't swap views by adding and removing them as subviews. You need to swap out view controller and their views using a UINavigationController or a UITabbarController. In Xcode File>New Project, there is a Navigation based project and a Tabbar based project templates. Either will provide you most of the code you need to implement a simple app using either controller.
It will be well worth your time to spend a day learning how to use these controllers properly. With your current design, your app will break if it gets much more than two views.
I'm halfway through implementing a very basic 'Add Contact' Button. I am calling the 'Add View' using the code (via a linked UIButton, that works) :
- (IBAction)showAddContact {
NSLog(#"Hit showAddContact");
ABNewPersonViewController *newPersonViewController = [[ABNewPersonViewController alloc] init];
addContactNavController = [[UINavigationController alloc] initWithRootViewController:newPersonViewController];
[self presentModalViewController:addContactNavController animated:YES];
}
and then I have also set the delegate resonse of:
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person {
NSLog(#"Hit newPersonViewController");
//ABContact *contact = [ABContact contactWithRecord:person];
[self.navigationController popViewControllerAnimated:YES];
}
in my header I have set:
#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#interface test2ViewController : UIViewController <ABNewPersonViewControllerDelegate> {
UINavigationController* addContactNavController;
}
- (IBAction)showAddContact;
#end
I have added the frameworks Addressbook and AddressBookUI.
The add dialog box comes up as expected, I can edit the contact, but I am not able to remove the modal View Controller from the view.
I have even duplicated the problem in a simple test project available here:link text
What am I missing?, I bet it is something extremely simple.
Thanks #norskben
Couple of problems:
You should release the ABNewPersonViewController after presenting it.
You present the ABNewPersonViewController as a modal dialog with presentModalViewController: but you remove it from the screen as if it was pushed on a UINavigationController with popViewControllerAnimated:. Instead you should either push and pop, or present and dismiss. (If you don't know what this means, read a little int he View Controller documentation)
Even though you implement the ABNewPersonViewControllerDelegate protocol, you never set the delegate property of the ABNewPersonViewController.