I have a UIView that is pushing a UITableViewController that is contained inside of a UITabBarController.
#import <UIKit/UIKit.h>
#interface ARViewController : UITableViewController<UITabBarControllerDelegate> {
IBOutlet UITabBarController* tabBarController;
}
#property(nonatomic,retain)IBOutlet UITabBarController* tabBarController;
#end
Here is my implementation
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
self.clearsSelectionOnViewWillAppear = NO;
self.title = #"AR";
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
tabBarController.delegate = self;
[self.view addSubview:tabBarController.view];
}
My UITabBarController is referenced to Files Owner. Why is it not appearing?
UITabBarController is always used as 'root controller'. Maybe you can try to use a root controller to contain a tableview. And it's not a common method to add a tabbar as a subview to a tableview.
Related
May somebody let me know:
How to navigate from one view to another view in single viewcontroller in iphone sdk? I have an application in which i want to push to next view and pop to previous view in a single View controller. How this functionality can be achieved?
Thanks in advance
You can add and remove your secondview.Like this to navigate
-(IBAction)navigate:(id)sender
{
[self.view addSubView:secondView];
}
and this one to po to first view
-(IBAction)popToFirstView:(id)sender
{
[secondView removeFromSuperView];
}
Note:- You can use animations for adding and removing view, if you want to give animated effects.
If you need a single view controller you can try using a UIScrollView, that contain the 2 view, and a button to scroll from a view to another... but if i can give a tip, it's better using 2 view controller and a navigation view controller
You need to use UINavigation Controller to get push and pop.
do this way
In AppDelegate.h file
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
//this will be your first screen
#property (strong, nonatomic) FavViewController *favViewController;
#end
In A*ppDelegate.m* file
#import "AppDelegate.h"
#import "FavViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize favViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//initialize view controller
favViewController = [[FavViewController alloc] initWithNibName:#"FavViewController" bundle:nil];
//add navigation controller
UINavigationController *favouriteView = [[UINavigationController alloc] initWithRootViewController:favViewController];
//add controller to witndow
self.window.rootViewController = favouriteView;
[self.window makeKeyAndVisible];
return YES;
}
#end
Now come to the UIViewController, where you want to load/push to new controller
to load/push to new controller use this code
//this will be next screen
DetailsViewController *detailsViewController = [[DetailsViewController alloc ]init];
[self.navigationController pushViewController:detailsViewController animated:YES];
to go back or pop controller use this
//now it will send back to parent screen
[self.navigationController popViewControllerAnimated:YES];
I have figured out the solution for this problem and here is the solution as below:-
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UIButton *backbtn;
IBOutlet UIButton *nxtBtn;
IBOutlet UILabel *label;
}
-(IBAction)nxt:(id)sender;
-(IBAction)ba:(id)sender;
#end
#import "ViewController.h"
#interface ViewController ()
#end
int count=0;
#implementation ViewController
- (void)viewDidLoad
{
label.text=[[NSUserDefaults standardUserDefaults] objectForKey:#"NavigtionNumber"];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
-(IBAction)nxt:(id)sender
{
count++;
label.text=[NSString stringWithFormat:#" navigation time %d",count];
[[NSUserDefaults standardUserDefaults] setObject:label.text forKey:#"NavigtionNumber"];
[[NSUserDefaults standardUserDefaults] synchronize];
ViewController *vc=[[ViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
-(IBAction)ba:(id)sender
{
count--;
label.text=[NSString stringWithFormat:#" navigation time %d",count];
[[NSUserDefaults standardUserDefaults] setObject:label.text forKey:#"NavigtionNumber"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self.navigationController popViewControllerAnimated:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Hope this will help others in future.
Thanks.
I have a view whose controller is being instantiated (NSLog says so), but the view doesn't show up. If I load it as a modal view it appears, but not if I allocate it.
I have this structure (MenuView is the view that doesn't appear):
// ViewController.h
#import "MenuViewController.h"
#class MenuViewController;
#interface ViewController : UIViewController<ASIHTTPRequestDelegate>{
...
IBOutlet MenuViewController *menuView;
}
...
#property(nonatomic, retain) MenuViewController *menuView;
#end
// ViewController.m
#import "MenuViewController.h"
#implementation ViewController
#synthesize menuView;
- (void)loadMenu{
// THIS WORKS
// [self presentModalViewController:menuView animated:YES];
// THIS DOESN'T (VIEWCONTROLLER IS INSTANTIATED BUT VIEW DOESN'T APPEAR
menuView = [[[MenuViewController alloc] initWithNibName:#"MenuView" bundle:Nil] autorelease];
[self.navigationController pushViewController:menuView animated:YES];
}
Some ideas:
Try using self.menuView when assigning:
self.menuView = [[MenuViewController alloc] initWithNibName:#"MenuView" bundle:Nil];
Also, probably shouldn't autorelease a property. Release it in dealloc and set it to nil in viewDidUnload.
Make sure that self (ViewController) has a navigationController. Was ViewController pushed/presented by a navigationController?
Is - (void)loadMenu{ being called from the MainThread? Check with [NSThread mainThread]
Check out some tutorials/examples:
Adding a Navigation Controller by Hand
NavigationController Application in iPhone
Tutorial: Introducing UINavigationController Part 1
iPhone View Switching Tutorial
I have a UINavigationController (to use like a wizard page) which I create programmatically and I need to display a "Cancel" button to cancel the process in any UIViewController.
Creating the UINavigationController:
FirstVC *firstVC = [[[FirstVC alloc] initWithNibName:#"FirstPage" bundle:nil] autorelease];
firstVC.delegate = self;
navigationController = [[UINavigationController alloc] initWithRootViewController:firstVC];
[self.view addSubview:navigationController.view];
Adding Cancel Button:
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelRequestNewLeave:)];
navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;
[cancelButton release];
But when I push a second page to UINavigationController the cancel button is not shown on the UINavigationBar. If I go back to first page, the cancel button is there. So, apparently the button is added only for the first view. I believe this is because I'm not subclassing UINavigationController, because I need to use it in a subview. But I don't know how to set the rightBarButtonItem in a UINavigationController which is created programmatically.
navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;
Can someone shed a light on this?
Thanks in advance.
The navigation item is per view controller. The navigation bar draws its contents from the navigation item of the view controller whose view it's currently framing, which corresponds to the view controller at the top of the navigation controller's stack.
You basically need each view controller to stick a cancel button in its navigation item. You can do any of the following:
Copy-paste the code into all relevant view controllers.
Move the code into a utility function or class and call that.
Create a common superclass for all relevant view controllers that handles setting up the cancel button for its subclasses.
You can also subclass UINavigationcontroller and overide few methods like this:
- (id)initWithRootViewController:(UIViewController *)rootViewController {
self = [super initWithRootViewController:rootViewController];
if (self) {
[self setCloseButtonToController:rootViewController];
}
return self;
}
- (void)dismissController {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)setCloseButtonToController:(UIViewController *)viewController {
UIBarButtonItem *closeItem = [[UIBarButtonItem alloc] initWithTitle:#"Close" style:UIBarButtonItemStylePlain target:self action:#selector(dismissController)];
[viewController.navigationItem setRightBarButtonItem:closeItem];
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
[super pushViewController:viewController animated:animated];
[self setCloseButtonToController:viewController];
}
You can instead adopt the UINavigationControllerDelegate protocol in the class which creates the UINavigationController instance. You can also create the cancelButton in advance and then implement navigationController:willShowViewController:animated: like this,
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
viewController.navigationItem.rightBarButtonItem = cancelButton;
}
You will have to remember to create and hold the cancelButton and not release it. This will also mean cancelRequestNewLeave: will have to be a method in class that creates the UINavigationController instance which is what it is right now I guess.
create CommonViewController
create FirstViewController (extends from CommonViewController)
create SecondeViewController (extends from CommonViewController)
add function common functions in the CommonViewController
like that
CommonViewController.h
#interface CommonViewController : UIViewController
-(void) initializeCartBarButton;
#end
CommonViewController.m
#import "CommonViewController.h"
#interface CommonViewController ()
#end
#implementation CommonViewController
-(void) initializeCartBarButton {
UIBarButtonItem *cartBarButton = [[UIBarButtonItem alloc] init];
cartBarButton.title = #"cart";
[cartBarButton setTarget: self];
[cartBarButton setAction: #selector(goToCart:)];
self.navigationItem.rightBarButtonItem = cartBarButton;
}
- (IBAction) goToCart:(id)sender {
NSLog(#"");
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
FirstViewController.h
#import <UIKit/UIKit.h>
#import "CommonViewController.h"
#interface FirstViewController : CommonViewController
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeCartBarButton];
}
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#import "CommonViewController.h"
#interface SecondViewController : CommonViewController
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeCartBarButton];
}
#end
note: you can add the code of initializeCartBarButton in the viewDidLoad of CommonViewController and delete this fuction from CommonViewController and from child class's
This is how I did it with UINavigationController subclass that is capable of dismissing every viewController pushed into it.
class CustomNavigationController: UINavigationController, UINavigationControllerDelegate{
//TODO: Use when we have more right bar button types.
var rightBarButtonType: RightBarButtonType = .Close
enum RightBarButtonType{
case Close
}
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
// MARK: Private Functions
private func addRightBarButtonTo(viewController: UIViewController){
let barButtonItem: UIBarButtonItem!
switch self.rightBarButtonType {
case .Close:
barButtonItem = UIBarButtonItem(image: UIImage(named: "ic_close_white"), style: .Done, target: self, action: #selector(CustomNavigationController.dismiss(_:)))
}
viewController.navigationItem.rightBarButtonItem = barButtonItem
}
// MARK: UINavigationController Delegate
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
self.addRightBarButtonTo(viewController)
}
#objc func dismiss(sender: AnyObject){
self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
}
}
You'll need to add the button in every view controller. You cannot do it by setting one once or sharing one between view controllers (in a sensible fashion). A good place to add the button is in the viewDidLoad method of your view controllers. You can create one basic UIViewConteoller subclass for them if you feel this gets to repetitive.
You can add a custom 'Cancel' UIButton directly to the NavigationBar's view instead of using the UIBarButtonItem.
UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton.imageView = // Some custom image
cancelButton.frame = CGRectMake(...); // Something far to the right.
[self.navigationController.navigationBar addSubview: cancelButton];
The normal way to do this is to add that cancel button to the navigationItem of every single view controller in your navigation stack. The above approach can make it simpler by allowing you to write less code, but it is a tiny bit of a hack.
Add this code in your rootview viewDidLoad method and implement the cancelMethod in rootview controller.This will be available in all the view controllers. you can adjust the button location by changing button frame.For orientation change you have manually adjust the location of button.
UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnCancel addTarget:self
action:#selector(cancelMethod)
forControlEvents:UIControlEventTouchDown];
[btnCancel setBackgroundImage:[UIImage imageNamed:#"image"]
forState:UIControlStateNormal];
btnCancel.frame = CGRectMake(280, 27, 45, 25);
[self.navigationController.view addSubview: btnCancel];
I am working on a tabbar project and in this i also have navigation controller. and i am doing below steps :-
Show the main screen
navigation from first tab to 5 next screens.
and on the 6th screen i want to show the tabbarcontroller and want to show my other tab bar.
i tried the below code :-
self.navigationController.tabBarController.hidesBottomBarWhenPushed = YES;
and some others. but did not get any success yet. so can any one suggest how to i do this?
Thanks
Create two files .h and .m without .xib
//.h file
#import <UIKit/UIKit.h>
#class Class1, Class2;
#interface TabbarController : UITabBarController
{
Class1 *class1;
Class2 *class2;
UINavigationController *nav1,*nav2;
}
#end
//.m file
#implementation TabbarController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
class1 =[[Class1 alloc] initWithNibName:#"Class1" bundle:nil];
nav1=[[UINavigationController alloc] initWithRootViewController:class1];
class1.title = #"class1";
class1.tabBarItem.image = [UIImage imageNamed:#"tab1.png"];
class1.navigationController.navigationBar.hidden = TRUE;
class2 =[[Class2 alloc] initWithNibName:#"Class2" bundle:nil];
nav2=[[UINavigationController alloc] initWithRootViewController:class2];
class2.tabBarItem.image = [UIImage imageNamed:#"tab2.png"];
class2.title = #"class2";
class2.navigationController.navigationBar.hidden = TRUE;
NSArray *controllers = [NSArray arrayWithObjects:nav1,nav2,nil];
self.viewControllers = controllers;
}
Redirect your view to this view wherever you need tabbar.
TRy it by this:
Create the Object of Delegate class
#import "DelegateClass.h"
DelegateClass *appDel;
Now in .m class
-(void)viewDidLoad
{
[super viewDidLoad];
appDel= (DelegateClass *)[[UIApplication sharedApplication]delegate];
}
Now just do like this in the View from where you are navigation,
appDel.tabBarController.hidesBottomBarWhenPushed = YES;
This was just a tricky part.It worked greatly for me :)
You have to use custom UItabBarController.
see creating custom TabBar Controller
I'd like to launch a modal view controller the way one does with 'ABPeoplePickerNavigationController' and that is without having to creating a navigation controller containing the view controller.
Doing something similar yields a blank screen with no title for the navigation bar and there's no associated nib file loaded for the view even though I am invoking the initWithNibName when the 'init' is called.
My controller looks like:
#interface MyViewController : UINavigationController
#implementation MyViewController
- (id)init {
NSLog(#"MyViewController init invoked");
if (self = [super initWithNibName:#"DetailView" bundle:nil]) {
self.title = #"All Things";
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"All Things - 2";
}
#end
When using the AB controller, all you do is:
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentModalViewController:picker animated:YES];
[picker release];
ABPeoplePickerNavigationController is declared as:
#interface ABPeoplePickerNavigationController : UINavigationController
The other way to create a modal view as suggested in Apple's 'View Controller Programming Guide for
iPhone OS':
// Create a regular view controller.
MyViewController *modalViewController = [[[MyViewController alloc] initWithNibName:nil bundle:nil] autorelease];
// Create a navigation controller containing the view controller.
UINavigationController *secondNavigationController = [[UINavigationController alloc] initWithRootViewController:modalViewController];
// Present the navigation controller as a modal view controller on top of an existing navigation controller
[self presentModalViewController:secondNavigationController animated:YES];
I can create it this way fine (as long as I change the MyViewController to inherit from UIViewController instead of UINavigationController). What else should I be doing to MyViewController to launch the same way as ABPeoplePickerNavigationController?
I'd like to launch a modal view controller the way one does with 'ABPeoplePickerNavigationController' and that is without having to creating a navigation controller containing the view controller
But this is exactly what ABPeoplePickerNavigationController is doing. It isn't magic, it is a UINavigationController that instantiates a UIViewController internally (a UITableView that is populated with your address book contacts) and sets the UIViewController as its root view.
You can indeed create your own similar UINavigationcontroller subclass. However, within it's initializer, you will need to create a view controller to load as its root view just like ABPeoplePickerNavigationController does.
Then you can do what you are trying like this:
[self presentModalViewController:myCutsomNavigationController animated:YES];
In the code you posted:
#interface MyViewController : UINavigationController
#implementation MyViewController
- (id)init {
NSLog(#"MyViewController init invoked");
if (self = [super initWithNibName:#"DetailView" bundle:nil]) {
self.title = #"All Things";
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"All Things - 2";
}
#end
I suspect you are having NIB issues. there isn't a "rootViewController" outlet to connect. This is why you have a blank screen.
The initalizer you should be using internally is this:
self = [super initWithRootViewController:myCustomRootViewController];