如何在使用UIPageViewController时将UIBarButtonItem添加到NavigationBar

12

请原谅我,关于如何在编程方式下将UIBarButtonItem添加到NavigationBar已经有很多问题了,但似乎我无法让任何解决办法在我的情况下起作用。

这是一个简单的测试应用程序布局,我一直在使用它来学习UIPageViewController。

storyboard

我已经成功地使用三个独特的viewControllers使页面视图控制器正常工作。现在,我想为每个视图控制器设置不同的rightBarButtonItems。我可以通过简单地执行以下操作,在DetailViewController中设置通用的barButtonItem

UIBarButtonItem *newButton = [[UIBarButtonItem alloc] initWithTitle:@"Whatever" 
                              style:UIBarButtonItemStylePlain 
                              target:self 
                              action:@selector(doSomething)];    

self.navigationItem.rightBarButtonItem = newButton;

考虑到我需要为pageViewController中的三个页面各自设计一个唯一的按钮,因此我无法在detailViewController中设置该按钮。我已经尝试了上述代码,在三个控制器的viewDidAppear方法中使用,但是按钮不会出现。我还尝试过以同样的方式创建按钮,然后进行以下设置,但没有成功。

DetailViewController *vc = [[DetailViewController alloc] init];
vc.navigationItem.rightBarButtonItem = newButton;

我知道我接近成功了,只是不确定如何指定需要向运行我的contentViewControllers所嵌入的detailViewController的NavigationBar添加一个按钮的NavigationController。任何帮助都将是极好的,特别是代码片段。

顺便说一下,我尝试过其他一些方法,但出现了问题:

  • viewDidLoad中设置按钮而不是viewDidAppear中设置
    • 这样做不起作用,因为viewDidLoad方法并不会在每次从一张页面划到另一张页面时都被调用。然而,viewDidAppear方法会被调用,因此我正在尝试在那里设置按钮。也有可能viewWillAppear被每次调用,但我没有检查。
  • 在UIPageViewController委托方法中设置按钮
    • 如果用户快速翻阅页面,则此方法存在问题,按钮将无法更改或无法显示。

解决方案

事实证明我已经接近成功了...我只需要在我的三个视图控制器中创建一个navigationItem属性,而不是在UIPageViewController方法中创建按钮。当控制器在委托方法中被实例化时,我只需要将navigationItem属性设置为detailViewController的属性。这样,在我的viewDidApper方法中,我就可以创建按钮了。然后在viewWillDisappear时,我将按钮设置为nil。您也可以在DetailViewControllerviewdidLoad中创建按钮,并在各个视图控制器的viewDidAppear中更改文本和操作。以下是一个示例:

在委托方法中:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController

根据viewController的索引,我调用一个辅助方法。当调用这个辅助方法时,它会实例化视图控制器。实例化后,我设置一些属性,包括navigationItem属性。

-(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;

}

然后在视图控制器的viewDidAppear中,我只需这样做

-(void)viewDidAppear:(BOOL)animated
{

    UIBarButtonItem *newButton = [[UIBarButtonItem alloc]
                               initWithTitle:@"Whatever" style:UIBarButtonItemStylePlain target:self action:@selector(doSomething)];
    navItem.rightBarButtonItem = newButton;

}

你的视图控制器中的navItem属性是什么? - Pedro Borges
3个回答

2

如果您需要按钮在查看页面更改时每次也更改,那么必须在您尝试的代理方法之一中完成。然而,我建议您不要创建新的按钮并将其设置为导航项,而是仅更改标题。

您可以在界面构建器中创建按钮,并将其链接到DetailViewController中的属性,然后每次转到新页面时,使用UIControlStateNormal调用方法更改该按钮的标题。

如果您需要按钮对于每个页面执行不同的操作,我建议在按钮的操作方法中检查当前页面,而不是每次声明一个新的按钮。


1
由于您的答案,我被迫尝试并使委托方法对我起作用。经过一些故障排除,我意识到了之前尝试使用vc.navigationItem.rightBarButtonItem等设置按钮时出现的问题。本质上我正在创建一个新的navigationItem并向其中添加一个按钮。由于navigationController的特性,新的navigationItem不会出现在其顶部。然后我意识到我可以通过委托方法从我的DetailViewController传递navigationItem属性到我的单独页面视图控制器中。谢谢! - Ben

1
您可以通过在其中一个分页视图控制器中找到页面控制器,然后获取其导航项来找到正确的导航项以设置按钮/标题。例如:
UIViewController *pageController = [[self.navigationController childViewControllers] lastObject];
pageController.navigationItem.title = @"My page's title";

很烦人的是self.navigationItem不起作用!


0

我的一位同事也遇到了页面视图控制器的同样问题。

据我所知,在UIPageViewController的成员视图控制器中,您无法将UIBarButtonItem添加到导航栏中。原因是'navigationController'对于UIPageViewController设置为nil。要确认,请打印[UIPageViewController navigationController]的值。

但是,您可以采取一种方法来克服此问题。请下载示例PhotoScroller

并在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;
}

在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;
}

为了避免崩溃,您必须在AppDelegate.m中正确处理UIPageViewControllerDataSource委托方法。
尽管如此,我不建议您这样做,因为它会破坏UIPageViewController的整个概念。
希望这对您有所帮助。

Hitesh,感谢您的建议,但我将避免这条路!只要您的UIPageViewControllerDataSource嵌入到导航控制器中,您实际上可以将UIBarButtonItems添加到navBar中。我在问题中提供的示例基本上将UIPageViewController成员放置在Master-Detail应用程序的detailViewController之上。这样,导航栏仍然保持活动状态。我曾忽略将detailViewController的navigationItem属性传递给我的pageViewController成员。一旦意识到这一点,这就是一个简单的任务!再次感谢 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接