My app layout is as follows -
the rootViewController is a tabViewController with 3 tabs each having a UINavigationController as their rootViewController. Within one of these tabs I am pushing upon cell selection to another tabController which now has two tabs. What I am trying to do is set the rightBarButtonItem on each of these two tab's viewControllers... in the viewDidLoad method of both of these I am doing:
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(selectionChanged:)];
however this is doing absolutely nothing! I thought from the apple documentations that you could set the navigationItem's rightBarButtonItem from anywhere within your navigation controllers view hierarchy but that doesn't seem to be the case here. Any idea what - if anything - I am doing wrong?
The solution to this is to instead of simply setting the rightBarButtonItem on self.navigationItem we need to set it on the parent tabBarController like so :
self.tabBarController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(selectionChanged:)];
Related
I am converting an app that is written in ios 2 to ios 9. I am not really familiar with ios 2 and I need some help. Back in ios 2 there were no view controllers and xib files were used. There was one xib file called the main window which would hold all the navigation items. In my case the main window xib has a navigation bar. And in code there is the following line
self.navigationItem.title = #"Back";
So I could see when i run the app on a simulator, in one of my views there is a button with titled "Back". But i cannot find a method for this button. Like there is no IBAction for it or a method. I am trying to add a selector for the navigationitem but it doesn't work. This is what I tried:
self.navigationItem.selector = #selector(backButtonClicked:)
How can I add a selector to a navigationItem so I can search that in the project or create my own selector.
You can add custom back button to your navigation bar this way
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(backButtonClicked:)];
self.navigationItem.leftBarButtonItem = btn;
-(void)backButtonClicked: (id)sender
{
[self.navigationController popViewControllerAnimated: YES]; // or popToRoot... if required.
}
Similar to the issue described here, with the exception that my TabBar is actually showing the BackButton on my NavigationBar is not. In the question I provided a link to the answer that solved the problem was that there was a NavigationController within a NavigationController, I do not have that so this is a different issue.
The basic flow of my storyboard is Login (UIView) - TabBar (UITabBarController) - NavigationController (UINavigationController) - Actual visible screen (UITableViewController) - New TableView where the issue occurs (UITableViewController).
On the new actual visible screen or the TableView the NavigationBar at the top shows just fine and I can click in the general area that the BackBarButton should be and it will go back, but no BackBarButton item is visible.
I tried changing the color, allocating it in the previous ViewController, making sure it was visible, etc. And none of them have shown the Back Button. It seems to be there but it is not shown.
Any ideas? From the other question that is similar to my issue this seems to be a iOS 9 specific thing.
EDIT from looking at the Debug View Hierarchy I can tell that the back button is in fact there but it just has no label or back arrow on it. How can I make the back label visible?
EDIT 2
Here is the viewDidLoad method of the view controller where the back button should appear.
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#" " style:UIBarButtonItemStylePlain target:nil action:nil];
[self.navigationItem.backBarButtonItem setTintColor:[UIColor whiteColor]];
// Other unimportant stuff
}
The way I am segueing to this view controller is through the storyboard with a Push segue. Code is below.
- (void)segueToUser: (UIButton*)button {
long row = button.tag;
PFObject *PFQuote = [_recent quoteAtIndex:(row-1)/2];
PFUser *u = [PFQuote objectForKey:#"creator"];
_send = u;
[self performSegueWithIdentifier:#"showUser" sender:self];
}
Here is my prepareForSegue in the same file as the segueToUser
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showUser"]) {
BRETTFUserTableViewController *bfutvc = [segue destinationViewController];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#" " style:UIBarButtonItemStylePlain target:nil action:nil];
bfutvc.us = _send;
}
}
Here is a picture of a section of my storyboard.
The first view is a tabView
The second view is a navView
The third view is a tableView
The fourth view is a tableView
Since no one has seemed to have found a solution I will provide additional information. From my digging deeper into the Debug View Hierarchy I have found some more information regarding the backButton. I can see that the back arrow is intact there and there is a NSString next to it that seems to be nil, I do not know why it is nil but that is what I found. Here are additional pictures of what I have found.
In your
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
you have Write a code line
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#" " style:UIBarButtonItemStylePlain target:nil action:nil];
In Above line you have set title " " Empty String.
Instead of empty string use the title which you want to show on back-button item. fr ex:
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
Check it might that help.
Adding a image of storyboard, how i have embedded the view controller in navigation controller.
or in case if you have put navigation appearance code anywhere in your app then also post that code.
In your viewDidLoad and prepareForSegue methods you have this :
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#" " style:UIBarButtonItemStylePlain target:nil action:nil];
Which replace the default back button of the navigation controller by a button without a label.
You should simply remove these 2 lines to have the default back button.
I have finally solved the issue. To accomplish this I had to go into the navigation bar for the first tableViewController and set the Back Button title to Back and then set the tint color (as it defaulted to clear) and now it works.
I want to add buttons to my navigation bar through code, but they are not appearing for me. I think it might have to do with my navigation bar being inside a UIView.
My code in viewDidLoad:
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(add)];
self.navigationItem.rightBarButtonItem = addButton;
Interface builder:
Any help would be greatly appreciated!
You shouldn't add a navigation bar directly in your view hierarchy. Rather, add a navigation controller, have your view controller as the root controller of the navigation controller, and set the navigation controller as the initial controller of the storyboard (or as the destination controller of segues, etc.).
Please forgive me, there are already a ton of questions on how to add a UIBarButtonItem to a NavigationBar programmatically but I just can't seem to get any of the solutions to work in my situation.
Here is the layout of a simple test app I have been working with to learn the UIPageViewController.
I have the page view controller working nicely with three unique viewControllers. I would now like to set unique rightBarButtonItems for each of the view controllers. I can easily set a common barButtonItem in the DetailViewController by simply doing this.
UIBarButtonItem *newButton = [[UIBarButtonItem alloc] initWithTitle:#"Whatever"
style:UIBarButtonItemStylePlain
target:self
action:#selector(doSomething)];
self.navigationItem.rightBarButtonItem = newButton;
Given that I need a unique button for each of the three pages in the pageViewController I am not able to set the button in the detailViewController. I have tried the code above in viewDidAppear of the three controllers but the buttons will not appear. I have also tried creating the button in the same way and then setting it like this with no luck.
DetailViewController *vc = [[DetailViewController alloc] init];
vc.navigationItem.rightBarButtonItem = newButton;
I know I'm close here, I'm just not sure how to specify I need to add a button to the NavigationBar of the NavigationController that is running the detailViewController that my contentViewControllers are embedded in. Any help would be great ESPECIALLY SNIPPETS.
As a side note I have tried a few other methods that have come up problematic.
Setting the button in viewDidLoad rather than viewDidAppear
This will not work because the viewDidLoad method is not called everytime you swipe from one page to the next. The viewDidAppear method is however so I am trying to set the button there. It is possible viewWillAppear is called everytime but I haven't checked.
Setting the button in the UIPageViewController delegate methods
This is problematic if the user flips through the pages to quickly the button will fail to change or fail to appear.
SOLUTION
It turns out I was close… Rather than creating the button in the UIPageViewController methods I simply needed to create a navigationItem property in each of my three view controllers. When the controllers are instantiated in the delegate methods I simply set the navigationItem property equal to that of the detailViewController. That way in my viewDidApper methods I could create the button. Then at viewWillDisappear I set the button to nil. You can also just create the button at viewdidLoad of the DetailViewController and change the text and action in viewDidAppear of the individual viewControllers. Here is a sample.
In the delegate methods
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
I call a helper method based on the index of the viewController. The helper method instantiates the view controllers when it is called. Once instantiated I set some properties including the navigationItem property.
-(FirstController *)controllerAtIndex:(NSUInteger)index
{
FirstController *fvc = [self.storyboard instantiateViewControllerWithIdentifier:#"FirstPageController"];
fvc.imageFile = self.pageImages[index];
fvc.titleText = self.pageTitles[index];
fvc.pageIndex = index;
fvc.navItem = self.navigationItem;
return fvc;
}
Then in the viewDidAppear of the viewController I just do this
-(void)viewDidAppear:(BOOL)animated
{
UIBarButtonItem *newButton = [[UIBarButtonItem alloc]
initWithTitle:#"Whatever" style:UIBarButtonItemStylePlain target:self action:#selector(doSomething)];
navItem.rightBarButtonItem = newButton;
}
If you need the button to change each time you change the page you look at, it must be done in one of the delegate methods that you have tried. I suggest however, that instead of creating a new button and setting it to the navigation item, you simply change the title.
You can create the button in interface builder and link it to a property in your DetailViewController and then call setTitle:forState with UIControlStateNormal on the button every time you go to a new page.
If you need the button to do something different for each page, I would recommend checking the current page in the buttons action method rather than declaring a new one each time.
You can find the correct navigation item to set buttons/titles on by finding the page controller in one of its paged view controllers, then getting its nav item. e.g.
UIViewController *pageController = [[self.navigationController childViewControllers] lastObject];
pageController.navigationItem.title = #"My page's title";
It's really annoying that self.navigationItem doesn't work!
One of my colleagues experienced the same problem with page view controller.
As far as I understand, you wont' be able to add UIBarButtonItem to navigation bar of member view controllers in UIPageViewController. Reason being 'navigationController' is set to nil for UIPageViewController. To confirm, print value of [UIPageViewController navigationController].
However you can do one thing to overcome this issue. Please download example PhotoScroller.
And do following changes in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// kick things off by making the first page
PhotoViewController *pageZero = [PhotoViewController photoViewControllerForPageIndex:0];
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:pageZero];
if (pageZero != nil)
{
// assign the first page to the pageViewController (our rootViewController)
UIPageViewController *pageViewController = (UIPageViewController *)self.window.rootViewController;
pageViewController.dataSource = self;
[pageViewController setViewControllers:#[nav]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];
}
return YES;
}
And following changes in the PhotoViewController.m
- (void)loadView
{
.....
.....
self.title =#"Frogs";
UIBarButtonItem *newButton = [[UIBarButtonItem alloc] initWithTitle:#"Something" style:UIBarButtonItemStylePlain target:self action:#selector(doSomething)];
[newButton setTintColor:[UIColor redColor]];
self.navigationItem.rightBarButtonItem = newButton;
}
To avoid crash, you have to handle UIPageViewControllerDataSource delegate methods correctly in AppDelegate.m
Though, I wouldn't advice you to do above as it breaks the whole concept of UIPageViewController.
I hope this would be helpful.
I am trying to add a bar button to my iOS app and can't get it to show up. I can see the bar in the Navigation Item's view hierarchy by setting a breakpoint. If it helps, I chose 'Embed Navigation Controller'. Any idea what's going on?
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(choosePreferredTerm:)];
[self.navItem setRightBarButtonItem:item animated:YES];
Here is the connection in IB
This is what the embedded Navigation Controller looks like:
This is what it looks like on the sim:
Try this rather than using custom outlet "navItem" also insure your application has a navigation controller in place
self.navigationItem.rightBarButtonItem = barButton;