在 UIPageViewController 中重新加载视图

Posted

技术标签:

【中文标题】在 UIPageViewController 中重新加载视图【英文标题】:Reloading Views in UIPageViewController 【发布时间】:2014-07-03 10:21:28 【问题描述】:

我正在制作一个 ios 应用程序,它有一个加载了默认页面的 UIPageViewController,如果还没有添加任何其他页面,并且用户可以在他通过应用程序的过程中添加页面。但是,初始视图不会随着其他视图的添加而改变。

我已经尝试了这些问题的答案:Is it possible to Turn page programmatically in UIPageViewController?Changing UIPageViewController's page programmatically doesn't update the UIPageControlRemoving a view controller from UIPageViewControllerRefresh a UIPageViewController

它们都不适合我。在我重新加载应用程序之前,视图仍保留在初始页面,之后页面显示正常,我可以添加任意数量的页面。

这是我用于制作 PageView 和页面的代码

- (void)viewDidLoad

    [super viewDidLoad];

    self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];

    self.pageController.dataSource = self;
    [[self.pageController view] setFrame:[[self pageControllerView] bounds]];

    UIViewController *initialViewController = [self viewControllerAtIndex:0];

    __block Page1ViewController *blocksafeSelf = self;

    // This doesn't work either... :(
    void (^completionBlock)(BOOL) = ^(BOOL finished)
    
        // It seems that whenever the setViewControllers:
        // method is called with "animated" set to YES, UIPageViewController precaches
        // the view controllers retrieved from it's data source meaning that
        // the dismissed controller might not be removed. In such a case we
        // have to force it to clear the cache by initiating a non-animated
        // transition.
        usleep(1);
        dispatch_async(dispatch_get_main_queue(), ^()
            [blocksafeSelf.pageController setViewControllers:@[initialViewController]
                                      direction:UIPageViewControllerNavigationDirectionForward
                                       animated:NO
                                     completion:nil];
        );
    ;

    [self.pageController setViewControllers:@[initialViewController]
                              direction:UIPageViewControllerNavigationDirectionForward
                               animated:YES
                             completion:completionBlock];

    [self addChildViewController:self.pageController];
    [[self view] addSubview:[self.pageController view]];
    [self.pageController didMoveToParentViewController:self];


- (void)reloadViews

    [[self childViewControllers] makeObjectsPerformSelector:@selector(removeFromParentViewController)];
    [[self.view subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

    [self.pageController willMoveToParentViewController:nil];
    [self.pageController removeFromParentViewController];
    [self.pageController.view removeFromSuperview];
    self.pageController = nil;
    self.pageController = [[UIPageViewController alloc] init];

    [self.view setNeedsDisplay];


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

    NSUInteger index = ((SomethingViewController *)viewController).index;
    index++;

    if (index >= [Settings somethings].count)
    
        return nil;
    

    return [self viewControllerAtIndex:index];


- (UIViewController *)viewControllerAtIndex:(NSUInteger)index

    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Storyboard_iPhone"
                                              bundle:nil];
    if ([Settings somethings].count == 0 && index == 0)
    
        NoSomethingViewController *vc = [sb instantiateViewControllerWithIdentifier:@"NoSomethingViewController"];
        vc.index = index;
        return vc;
    

    SomethingViewController *childViewController = [sb instantiateViewControllerWithIdentifier:@"SomethingViewController"];
    childViewController.something = [[Settings somethings] somethingAtIndex:index];
    childViewController.index = index;

    return childViewController;

当应该创建一个新页面时,通过在somethings 数组中添加一个something,我从添加something 的视图控制器调用reloadViews。然后代码会到达viewControllerAtIndex 的第二部分,但这并没有显示在我在手机上看到的页面上,因为我仍然看到 NoSomethingViewController 和它的视图。

如果您需要更多代码,我会提供。

【问题讨论】:

你想做什么?您正在尝试滚动并且 UIPageIndicator 页面没有更改,或者您尝试在 UIPageViewController 加载页面后添加额外页面? 当我添加something时,我正在尝试重新加载页面视图控制器以显示不同的页面 我不认为您可以在加载页面视图控制器后重新加载它。您可以做的一件事是,如果某些事情发生了变化,则从超级视图中删除页面视图控制器并再次添加它,以便在某些事情发生变化时加载动态页面。 我在viewDidLoad方法的开头做。如果页面控制器已经存在,将其移除;重新创建它。它什么也没做。 是的,但是当您当时必须在页面视图控制器中添加新页面时,也将其从超级视图中删除并再次添加页面视图控制器,通过这样做 pageviewController 委托将被再次调用并在 pageviewcontroller 编号的页面将自动刷新。 【参考方案1】:

在pageViewController viewWillAppear方法中添加如下代码

数据源 = 自我

并在视图中添加WillDisappear

数据源 = 无

这将强制 pageViewController 重新加载其数据源

【讨论】:

【参考方案2】:

要显示当前点,别忘了你必须更新页面指示器

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController

示例如何更新您的 UIPageControl 指示器 https://***.com/a/22576250/3897011

【讨论】:

【参考方案3】:

在浪费了 Apple 的支持票很久之后,我决定采用另一种方法。

在我的 Storyboard 中,我创建了 2 个不同的导航控制器,每种情况一个(如果有 somethings,如果没有),我有一个初始视图控制器,在 viewDidAppear 上实例化其中一个两个并提出它。这样,我可以确保正确地重新加载整个导航控制器。

UINavigationController *nc;

if ([Settings somethings].count)

    nc = [self.storyboard instantiateViewControllerWithIdentifier:@"NavigationController"];

else

    nc = [self.storyboard instantiateViewControllerWithIdentifier:@"NoSomethingNavigationController"];


self.nc = nc;

[self presentViewController:nc animated:NO completion:nil];

【讨论】:

【参考方案4】:

为了重新加载UIPageViewController,您可以使用以下代码:

[self.pageController setViewControllers:@[yourCurrentController]
                                      direction:UIPageViewControllerNavigationDirectionForward
                                       animated:NO
                                     completion:nil];

也请实施

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

方法。

【讨论】:

请检查代码。我已经有[self.pageController setViewControllers:@[yourCurrentController] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; 如果我没有viewControllerBeforeViewController,程序将无法运行。这只是默认的(如果索引> 0索引--),所以我没有将它复制到问题中 是的。在 viewDidLoad 方法中。当你想重新加载 UIPageViewController 时,你应该再次使用它。 当我调用 reloadViews 时,再次调用 viewDidLoad 方法。 奇数。顺便说一句,您应该调用 [super viewDidLoad] 是的,我知道这很奇怪,而且我自己也无法弄清楚,这就是我在这里问的原因。 [super viewDidLoad] 已添加到问题中。

以上是关于在 UIPageViewController 中重新加载视图的主要内容,如果未能解决你的问题,请参考以下文章

UIPageViewController 背景在 Objective C iOS 中从不透明

获取 UIPageViewController 的滚动位置

在故事板中使用 UIPageViewController

如何在 UIPageViewController 和孩子之间正确传递对象

使用 UIPageViewController 在多个视图控制器之间滑动

带有 Peeking 的 UIPageViewController