In my app I am using storyboard, I need to change the title on a viewController. I am doing it as follows. In the .h file:
#property(weak, nonatomic) IBOutlet UINavigationItem *navBar;
And in the .m file:
#synthesize categoriaDescription,navBar;
...
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *category = self.categoriaDescription;
NSLog(#"Value of category = %#", category);
[self.navBar setTitle:category];
...
The default title is not changed, it should be 'A', the value of 'category' in this case. The Log shows 'A'.
Any help is welcome.
Why don't you simply use NavigationController?
realize that viewController.navigationItem does not have any sense if the viewController does not belongs to the navigationController's stack
[self.navigationController setTitle:#"myTitle"];
This should work.
EDIT:
If you do not have a navController on your storyboard
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self];
[navController setTitle:#"myTitle"];
[self.view addSubview:navController.view];
Related
UITabbarController.xib has UILabel as SubView.
When i run the app UILabel is not visible as the child view controllers are hiding UILabel.
I wanted that UILabel to be visible in all the ChildView controllers.
When I debug the code in viewDidLoad and viewWillAppear that label looks nil object though i have IBOutlet connection in the TabBarController.h file.
I have Code like this
in .h file
#interface TestTabBarController : UITabBarController <UITabBarControllerDelegate>
#end
and in .m file
#interface TestTabBarController ()
#property (weak, nonatomic)IBOutlet UILabel *historylabel;
#end
#implementation TestTabBarController
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]){
}
return self;
}
-(void)setChildrenViewControllers
{
// Set the View Controllers.
FirstViewController *viewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *viewcontroller2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
ThirdViewController *viewController3 = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
FourthViewController *viewController4 = [[FourthViewController alloc] initWithNibName:#"FourthViewController" bundle:nil];
self.viewControllers = #[viewController,viewcontroller2,viewController3,viewController4];
self.delegate = self;
}
#end
I am calling the Tabbarcontroller class as follows
TestTabBarController *testtabbar = [[TestTabBarController alloc] initWithNibName:#"TestTabBarController" bundle:nil];
[testtabbar setChildrenViewControllers];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:testtabbar];
[self.navigationController presentViewController:navController animated:YES completion:nil];
I have Xib for the UITabbarController subclass - which is a view.If i add the label on top of view in xib it will not display if because viewcontroller is subclass of tabbarcontroller.tabbarcontroller accepts only tabbar as subview and it will not accept labels.So We have to add items to each child controller or else in viewdidload of tabbarcontroller class create a label alloc and init it and add it like
[self.view addsubview:label];
if you add label on xib view then it will not be visible on child view controllers,if you load nib forcefully in viewdidload then nib will be visiblw but not tabbarcontroller and child view controllers.Hope this will help everyone.
I have a UINavigationController and I'm trying to release from memory every UIViewController once another one is on top of the stack. I assign the viewControllers property of the UINavigationController to the new UIViewController and then pop into it. This way I always have just one UIViewController in stack. However, the memory keeps adding up every time I create a new UIViewController. Dealloc is called, but the memory usage remains the same.
You can download the example project HERE
FirstViewController.h
#import "SecondViewController.h"
#interface FirstViewController : UIViewController
-(IBAction)goToSecond:(id)sender;
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", self.navigationController.viewControllers);
}
-(void)goToSecond:(id)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
[self.navigationController setViewControllers:#[secondVC]];
[self.navigationController popViewControllerAnimated:NO];
}
-(void)dealloc{
NSLog(#"FirstVC dealloc");
}
#end
SecondViewController.h
#import "FirstViewController.h"
#interface SecondViewController : UIViewController
-(IBAction)goToFirst:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", self.navigationController.viewControllers);
}
-(void)goToFirst:(id)sender{
FirstViewController *firstVC = [[FirstViewController alloc]init];
[self.navigationController setViewControllers:#[firstVC]];
[self.navigationController popViewControllerAnimated:NO];
}
-(void)dealloc{
NSLog(#"SecondVC dealloc");
}
#end
Navigation controller should not be used as you intended.
You should call pushViewController and popViewController for present/dismiss your viewControllers.
If you have memory issues, try to release memory in didReceiveMemoryWarning callback
I'm not sure about the benefit of a uinavigationcontroller but anyway you could add this snippet on your .m of your uiviewcontrollers
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
if (self.navigationController.viewControllers.count > 1) {
NSMutableArray *newViewControllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[newViewControllers removeObject:[controllers objectAtIndex:1]];
self.navigationController.viewControllers = newViewControllers;
}
}
And instead of
[self.navigationController setViewControllers:#[firstVC]];
[self.navigationController popViewControllerAnimated:NO];
you can set
[self.navigationController pushViewController:[[FirstViewController alloc] init] animated:NO];
You are using pop to go further, but you need to use push if you want to go to the next ViewController.
-(void)goToSecond:(id)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
[ self.navigationController pushViewController:secondVC animated:YES];
}
And in the SecondViewController to go back to your FirstViewController you should use pop
-(void)backToController
{
[self.navigationController popViewControllerAnimated:YES];
}
In your case
-(void)goToFirst:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
I uploaded a simple app to GitHub, with the fake navigation bar that i was talking about in my comment, hope it helps for your needs: https://github.com/yosihashamen/HelpersApps
Be ware that you must keep on "BaseViewController" alive at all times.
What I mean is something like this.
In your FirstViewController use presentViewController instead of push adding a new UINavigationController to the SecondViewController
-(void)goToSecond:(id)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:secondVC];
[self presentViewController:nav animated:YES completion:NIL];
}
In the SecondViewController add an UIBarButtonItem to the Navigation bar
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleDone target:nil action:#selector(goToFirst:)];
self.navigationItem.backBarButtonItem = backButton;
And implement dismiss method.
-(void)goToFirst:(id)sender
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
Try out setViewControllers:animated:
This allows you to explicitly set the view controllers on the UINavigationController stack, like you are doing, and it will automatically handle the navigation animation without you having to call popViewControllerAnimated:
This is useful if you have a multi-view journey where you need to get rid of the screens that have been shown so far but maintain the navigation animation (eg. app demo on launch) or if you want to easily push multiple view controllers on the navigation stack at once.
Apple doc here: https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html#jumpTo_21
P.S: Please do not suggest me to go with the app delegate way as I will use that in the middle of my app views. Thanx.
I try to use a UINavigationController to display a UITableView like the settings app. So I am trying to start step by step. So far, I try to show up a view contained in a view controller in the navigation stack. But I am missing something somewhere.
Here is my relevant code:
.h file:
#interface ViewController : UINavigationController{
UINavigationController *navigationController;
UIViewController *viewController;
}
#property(nonatomic, strong)IBOutlet UINavigationController *navigationController;
#property(nonatomic, strong)IBOutlet UIViewController *viewController;
#end
.m file :
#implementation ViewController
#synthesize navigationController;
#synthesize viewController;
- (void)viewDidLoad
{
[super viewDidLoad];
//Do any additional setup after loading the view, typically from a nib.
self.viewController = [[UIViewController alloc]init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.navigationController.view addSubview:self.viewController.view];
}
**The xib file:**
When I run the app, I am expecting to see the blue view, but all I see is the default blue navigation bar, without even the "Root View Controller" title message.
If you connect UI from IB, try to delete these line (delete alloc, init)
// self.viewController = [[UIViewController alloc]init];
// self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
// [self.navigationController.view addSubview:self.viewController.view];
This link Should help you. You might want to go through this to shed better light on the problem you're having.
https://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/SecondiOSAppTutorial/Introduction/Introduction.html
I have a UI Toolbar with an Add BarButton. I want this to trigger an action in a subordinate viewController. I am stuck.
The toolbar is set up like this:
TopViewController.h
IBOutlet UIToolbar* toolbar;
#property (retain, nonatomic) IBOutlet UIToolbar *homeButton;
#property (retain, nonatomic) IBOutlet UIToolbar *addButton;
- (IBAction)homePlease:(id)sender;
- (IBAction)addStuff:(id)sender;
TopViewController.m
#class ItemViewController;
#import "ItemViewController.h"
- (IBAction)homePlease:(id)sender {
//NSLog(#"%s", __FUNCTION__);
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)addStuff:(id)sender {
NSLog(#"%s", __FUNCTION__);
[self.itemViewController insertNewObject:self]; <-----
}
ItemViewController:
- (void)insertNewObject:(id)sender {
//NSLog(#"%s", __FUNCTION__);
AddItemViewController *addItem = [[AddItemViewController alloc] initWithNibName:#"AddItem-iPad" bundle:nil];
// Create a new managed object context for the new item - set its persistent store coordinator
// to the same as that from the fetched results controller's context.
NSManagedObjectContext .......
[self.addContext setPersistentStoreCoordinator:[[self.fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
addItem.item = (DDItem *)[NSEntityDescription insertNewObjectForEntityForName:#"Item" inManagedObjectContext:context];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:addItem];
nc.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:nc animated:YES completion:nil];
}
The Home button works fine.
The addButton fires (I see the log). But nothing else happens. The Add button is wired to the IBAction.
Any advice will be most welcome
It seems that this answer is correct. You must set the buttons within their presenting view controllers. I hope this helps others.
I have a navigation based application.On click of a button on the navigation bar in the first screen , I am able to push another view controller as follows :
-(void) buttonClicked:(id)sender
{
UIViewController* mv = [[SecondViewController alloc] init];
[[self navigationController] pushViewController:mv animated:YES];
}
Now i have a UIView(separate .h and .m files) as part of the first screen. On click of a button in the UIView, i want to push the SecondViewController.
I have tried the following :
UIViewController* mv = [[SecondViewController alloc] init];
UIViewController * home=[[FirstViewController alloc]init];
[[home navigationController] pushViewController:mv animated:YES];
It doesnt work!! Kindly help
UIViewController* mv = [[SecondViewController alloc] init];
UIViewController * home=[[FirstViewController alloc]init];
[[home navigationController] pushViewController:mv animated:YES];
The problem here is that home isn't part of the navigation stack, so [home navigationController] is surely nil. I'm not quite clear on what you're trying to do here, but just creating a view controller doesn't mean that it's actually part of the view controller graph.
Why would it work? Randomly creating view controllers whose view is not even visible, is not the solution. You can either keep a reference to the VC in the view like this:
#imlementation ViewController
- (id) init
{
// ...
aView = [[CustomView alloc] init];
aView.viewController = self;
// ...
}
#end
#interface CustomView
#property (assign) ViewController *viewController;
#end
Or you can search the responder chain at runtime:
UIResponder *next = [view nextResponder];
while (next)
{
if ([next isKindOfClass:[ViewController class]])
{
break;
}
next = [next nextResponder];
}
And now "next" will contain the view controller (or nil if it can't be found).
Try using the same navigationController to push view, this keeps the same stack of ViewControllers.
UIViewController* mv = [[SecondViewController alloc] init];
[[self navigationController] pushViewController:mv animated:YES];
[mv release];
I see your problem now! You need to #import your FirstViewController, then #class it. Then do your push.
So:
//.h
#import "FirstViewContoller.h"
#class FirstViewController;
#interface...
//.m
-(void)return {
FirstViewController *firstview = [[FirstViewController alloc]init(withnibname:)];
[firstView.navigationController pushViewController: firstView.navigationController.topViewController animated: TRUE];
}
If I am not wrong, your UIView though is in separate files, is still added to the screen from a UIViewController class.
Simply, post a notification from UIView to your FirstViewController class where you have access to the navigation controller. Then push the SecondViewController from there.
You Can use this. It Works very well for me:-
Firstly Create Object of AppDelegate in UIView Class and initialize it. Then create Navigationcontroller object in Appdelegate.h :-
#property(strong,nonatomic) UINavigationController *navControl;
In your UIView Class implement this code where you want to push :-
ViewController *objview = [[ViewController alloc]init]; [appDelegate.navControl pushViewController:objview animated:YES];