Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add UIBarButtonItem to NavigationBar while using UIPageViewController

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.

storyboard

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;

}
like image 330
Ben Avatar asked Feb 12 '14 16:02

Ben


People also ask

How do I add a navigation bar to my storyboard?

Go to the Storyboard. Select the View Controller and in The Editor menu select Embed in -> Navigation Controller. Next, drag a Bar Button from the Object Library to the left side of the Navigation Bar and name it "Left Item". Repeat this for the right side and name it "Right Item".

How do I customize the navigation bar in Swift?

With the NavigationController selected, go to the properties pane and uncheck, "Show navigation bar". Drag an ImageView containing your custom navigation bar image to the top of each ViewController. Add a button on top of the "Back" part of the navigation bar image and delete the button text.

What is navigationItem?

A Navigation Item represents the items that are displayed by a navigation bar so that the user can interact and navigate to other view controllers in the iOS applications. It is an instance of UINavigationItem class which inherits NSObject class. class UINavigationItem : NSObject.

What is navigation item in swift?

A navigation item always reflects information about its associated view controller. The navigation item must provide a title to display when the view controller is topmost on the navigation stack. The item can also contain additional buttons to display on the right (or trailing) side of the navigation bar.


2 Answers

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.

like image 170
mrosales Avatar answered Nov 07 '22 19:11

mrosales


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!

like image 24
Graham Perks Avatar answered Nov 07 '22 17:11

Graham Perks