I have a subclass of QLPreviewController that I'm pushing into a UINavigationController. I am able to show/hide the bottom toolbar using:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.toolbarHidden = NO;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.navigationController.toolbarHidden = YES;
}
But items I'm adding to the toolbar aren't showing up:
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *testButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Test"
style:UIBarButtonItemStylePlain
target:self
action:#selector(testButtonClicked:)];
NSArray *myToolbarItems = [NSArray arrayWithObjects:testButtonItem, nil];
self.toolbarItems = myToolbarItems;
[testButtonItem release];
}
Any advice would be very appreciated. Thanks.
Where are you allocating and initializing that view that is giving you the problem?
Are you using a splitViewController on iPad?
From the sound of it an object is sticking around for longer than necessary or when being called back it is not being re allocated and initialized properly before attempting to put it back on the stack, if you are using a splitViewController on iPad it handles it's views differently than a simple UINavigationController on an iPhone.
Related
So I have a root view with table view. I display the toolbar like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationController.toolbarHidden = NO;
}
And I implement the setToolbarItems method:
- (void)setToolbarItems:(NSArray *)toolbarItems animated:(BOOL)animated
{
UIBarButtonItem *buttonItem;
buttonItem = [[UIBarButtonItem alloc] initWithTitle:#"Hello" style:UIBarButtonItemStyleDone target:self action:#selector(goBack:)];
self.navigationController.toolbarItems = [ NSArray arrayWithObject: buttonItem ];
}
The result is an empty tolbar. Why?
From the docs:
toolbarItems
The toolbar items associated with the view controller.
#property(nonatomic, retain) NSArray *toolbarItems
Discussion
This property contains an array of UIBarButtonItem objects and works in >conjunction with a UINavigationController object. If this view controller is >embedded inside a navigation controller interface, and the navigation >controller displays a toolbar, this property identifies the items to display in >that toolbar.
You can set the value of this property explicitly or use the >setToolbarItems:animated: method to animate changes to the visible set of >toolbar items.
In other words, try accessing it through the actual view controller, not it's navigation controller like so:
self.toolbarItems = [ NSArray arrayWithObject: buttonItem ];
But who calls your implementation of setToolbarItems?
You're supposed to call setToolbarItems on your own view, not re-implement it. Then, the NavigationController will find them in the instance variable and render them.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationController.toolbarHidden = NO;
UIBarButtonItem *buttonItem;
buttonItem = [[UIBarButtonItem alloc] initWithTitle:#"Hello" style:UIBarButtonItemStyleDone target:self action:#selector(goBack:)];
[self setToolbarItems: [ NSArray arrayWithObject: buttonItem ]];
}
I have a requirement to load a UIWebView wrapped inside a UINavigationController, and show it on a modal view. UINavigationController should show the navigation bar at the top with a 'back' (I did not find back button, so I used 'done' button). I am not supposed to use a nib, so I have to do it programmatically only. The code has to basically serve as a library which can be integrated with any application. It has to work for IPhone and IPad, both.
This is what I have done so far:
I created a WebViewController class -
#interface WebViewController : UIViewController
{
UIWebView *m_cWebView;
}
#property (nonatomic, retain) UIWebView *m_cWebView;
#end
- (void)loadView
{
CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
webFrame.size.height -= self.navigationController.navigationBar.frame.size.height;
UIWebView *pWebView = [[UIWebView alloc] initWithFrame:webFrame];
pWebView.autoresizesSubviews = YES;
pWebView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
self.view = pWebView;
pWebView.scalesPageToFit = YES;
self.m_cWebView = pWebView;
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(back:)];
}
- (void)viewDidLoad
{
[super viewDidLoad];
if( m_cWebView != nil )
{
NSURL *url = [NSURL URLWithString:#"http://www.google.co.in"];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[m_cWebView loadRequest:request];
}
}
- (IBAction)back:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
return nil;
}
- (id)init
{
return self;
}
In the main view controller
#property (retain, atomic) UINavigationController *navCon;
-(IBAction)buttonPressed:(id)sender
{
if( navCon == nil )
{
WebViewController* webViewController = [[WebViewController alloc] init];
navCon = [[UINavigationController alloc] initWithRootViewController:webViewController];
}
[self presentModalViewController:navCon animated:YES];
}
So far, it is working fine. Now my issues:
I am totally new to iOS world. Is the above code correct or are there issues?
Code is supposed to be compiled with Xcode 4.2 with ARC, so I presume that I don't need to worry about memory.
Is the logic to calculate the initial size of WebView correct (I am taking the size of main screen and deducting the height of navigation bar)?
How do I handle orientation change such that on changing the orientation, my Navigation View and WebView both adjust to the new orientation?
Thanks
Edit:
I tried implementing with the rotation, but I have not been able to get it to work. willRotateToInterfaceOrientation is not getting called on my WebViewController, even though I am returning YES from shouldAutorotateToInterfaceOrientation ( and this method is getting called ). When I tried working with an empty nib ( loading WebViewController with this empty nib ), then it works fine.
Adding the 5th requirement:
One more additional requirement is that when this modal dialog dismisses, the view which presented this, should be in correct orientation (i.e. while the modal dialog is up, the orientation events are also passed on to the view which presented this modal view).
Thanks
Some points from my side.
Regarding back button, in place of done:
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];
Height of navigation bar is always 44.0f
You can handle orientation change with these methods:
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self adjustViewsForOrientation:toInterfaceOrientation]; // adjust your view frames here
}
I am not sure about your code and memory issues in that - so i could not comment over those.
Hope this information would be helpful to you.
I found the fix to the rotation problem.
Replace
- (id)init
{
return self;
}
with
- (id)init
{
if (self = [super init])
return self;
return nil;
}
and completely remove the following method:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
return nil;
}
Silly mistakes :)
Now it is rotating fine.
Can someone still comments on the original requirements?
I have the following:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath(NSIndexPath*)indexPath
{
audiChassisInputViewController = [[myAudiChassisInputViewController alloc] init];
[self.navigationController pushViewController:audiChassisInputViewController animated:YES];
self.navigationController.navigationBarHidden = NO;
UIBarButtonItem *retourButton = [[UIBarButtonItem alloc] initWithTitle:#"Retour" style:UIBarButtonItemStyleBordered target:self.navigationController action:#selector(popViewControllerAnimated:)];
[self.navigationController.navigationBar.topItem setLeftBarButtonItem:retourButton];
[self.navigationController.navigationBar.topItem setTitle:#"Chassis Input"];
[retourButton release];
[audiChassisInputViewController release];
}
and this workes...the new view is showed.
in the new view:
myAudiChassisInputViewController.h
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
chassisInputTextView.layer.cornerRadius = 15;
chassisInputTextView.clipsToBounds = YES;
[chassisInputTextView becomeFirstResponder];
UIBarButtonItem *okButton = [[UIBarButtonItem alloc] initWithTitle:#"OK" style:UIBarButtonItemStyleBordered target:self action:#selector(chassisOkPressed)];
[self.navigationController.navigationBar.topItem setRightBarButtonItem:okButton];
[okButton release];
}
I have no error, but there is no right bar button shown.Anyone, any idea why?
Change this line:
[self.navigationController.navigationBar.topItem setRightBarButtonItem:okButton];
with this line:
[[self navigationItem] setRightBarButtonItem:okButton];
The thing is, by the time viewDidLoad is executed, the top item of the navigation bar (self.navigationController.navigationBar.topItem) is still pointing to the navigation item of the back view controller.
The back view controller is the one that used to be the top view controller before the current top view controller was pushed onto the stack ([[viewControllers objectAtIndex:[viewControllers count] - 2] navigationItem]). The following snippet shows how the top item of the navigation bar is still pointing to the navigation item of the back view controller in viewDidLoad and it is for illustration purposes only:
// the view controllers currently on the navigation stack
NSArray *viewControllers = self.navigationController.viewControllers;
// The root view controller is at index 0 in the array, the back view controller is at index n-2, and the top controller is at index n-1, where n is the number of items in the array.
UIViewController *backViewController = [viewControllers objectAtIndex:[viewControllers count] - 2];
// get the navigation item of the back view controller
UINavigationItem *backNavigationItem = backViewController.navigationItem;
UINavigationItem *topItem = self.navigationController.navigationBar.topItem;
if (backNavigationItem == topItem) {
NSLog(#"This gets logged to the console");
}
Go to your
myAudiChassisInputViewController.m file
place following code
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIBarButtonItem *retourButton = [[UIBarButtonItem alloc] initWithTitle:#"Retour" style:UIBarButtonItemStyleBordered target:self.navigationController action:#selector(popViewControllerAnimated:)];
UIBarButtonItem *itemOkey=[[UIBarButtonItem alloc] initWithTitle:#"OK" style:UIBarButtonItemStyleBordered target:self action:#selector(chassisOkPressed)];
self.navigationItem.rightBarButtonItem=itemOkey;
self.navigationItem.leftBarButtonItem=retourButton;
}
I have the valid output as follows that you want to have
Hope it helps to you.
If you have xib file of your class, then add the navigation controller and add the navigation bar and under that add the UIBarButton.
Do UINavigationController buttons added need to be autoreleased? is this code ok?
Background - I'm seeing a range of navigation issues occuring in my application after I start triggering "memory warnings". I'm wondering if it is something to do with the question I posed here. Questions would include:
Is code below correct?
Any additional memory management code required elsewhere? (e.g. dealloc method? - I've currently got no code here to deallocate any buttons)
Any other tips re what might be going wrong with navigation bar populations/screen flow issues using a UINavigationController after simulating memory warnings
Code Below:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = [
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addAction:)] autorelease]; // IS AUTORELEASE HERE CORRECT?
self.navigationItem.leftBarButtonItem = self.editButtonItem;
self.title = #"Views";
thanks
I always just use autorelease and I think that it should do just fine.
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addAction:)]; // IS AUTORELEASE HERE CORRECT?
self.navigationItem.rightBarButtonItem = rightBarButton;
[rightBarButton release];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
self.title = #"Views";
}
I have already post this question but this time I post code. So I have a uiviewController, and in the viewDidLoad of this viewController I hide the backButton of the navigationController. After that, I push a new uiviewcontroller, and I set the backbutton to visible in the viewDidLoad, but the backbutton is still hidden...
Implementation of the first uiviewcontroller
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"page2page2page2page2page2";
self.navigationItem.hidesBackButton = TRUE;
}
-(IBAction)click
{
page3 *controller = [[page3 alloc] init];
[self.navigationController pushViewController:controller animated:YES];
[page3 release];
}
Implementation of the page 3
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"page3";
self.navigationItem.hidesBackButton = FALSE;
}
and the page3 has no backbutton, but the space is created for the button, because the tile "page 3" is on the right and not in the center... all this happen with the ios 4.2
thx
Neither of the above workarounds seemed to work for me. However when the third view was being displayed, i could see the button blink for a moment. So I suspected the problem (bug) has to do with the animation
When change animated to NO on the pushViewController the problem went away
- (IBAction)btnNext:(id)sender {
[[self navigationController] pushViewController:thirdViewController animated:NO];
}
My trick is setting setNavigationBarHidden to YES and immediately NO.
[self.navigationItem setHidesBackButton:NO animated:YES];
[self.navigationController setNavigationBarHidden:YES];
[self.navigationController setNavigationBarHidden:NO];
So as this the backButton not be animated but it's really work and my manager have not notice it ;P
I get the same behaviour and I must say I find it quite strange. I can't say why it doesn't work but as a workaround you can do:
In page2:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigationItem setHidesBackButton:YES animated:YES];
}
And in page3:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigationItem setHidesBackButton:NO animated:YES];
}
And remove the calls to self.navigationItem.hidesBackButton = ... in both controllers.
Well, I had the same problem running iOS 4.2. The back button would refuse to appear. Upon autoroating to landscape, it then appears. My solution was to do the following - This fixed the problem...or should we say its a workaround ;)
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.hidesBackButton = YES;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.navigationItem.hidesBackButton = NO;
}