pageViewController setViewControllers崩溃"无效参数不满意:[views count] == 3"

Bjö*_*örn 32 xcode

我知道还有其他几个这样的问题,但我无法找到解决问题的方法.我使用了一个显示不同ViewControllers的pageViewController.每次pageViewController向前移动时,我都会检查lastPage的输入.如果错误,pageViewController应该使用setViewController方法返回到该页面.没有这个方法一切正常,但如果我尝试使用它,应用程序崩溃与以下异常:

19:48:25.596 Phook[23579:60b] *** Assertion failure in -[_UIQueuingScrollView _replaceViews:updatingContents:adjustContentInsets:animated:], /SourceCache/UIKit_Sim/UIKit-2935.137/_UIQueuingScrollView.m:383  
2014-06-02 19:48:25.600 Phook[23579:60b] *** Terminating app due to uncaught   exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying:   [views count] == 3'
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished
   previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    if (completed && finished)
    {

        RegisterUserPageContent* lastPage = (RegisterUserPageContent*)previousViewControllers[ previousViewControllers.count-1];
        int lastIndex   = lastPage.pageIndex;
        int newIndex    = ((RegisterUserPageContent*)[self.pageViewController.viewControllers objectAtIndex:0]).pageIndex;

        if (newIndex > lastIndex)
        {   // Moved Forward
            if(!lastPage.testInput)
            {
                [self.pageViewController setViewControllers:@[ [self.storyboard instantiateViewControllerWithIdentifier:_pageStoryBoardIDs[0]] ]
                                         direction:UIPageViewControllerNavigationDirectionReverse
                                         animated:YES completion:nil];


            }
        }
        else
        {   // Moved Reverse

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如我已经说过的那样 我搜索了很多并实施了一些解决方案但没有任何帮助.谢谢.

小智 47

我遇到了同样的问题,并且能够使用这个答案的提示解决它/sf/answers/1468167571/.简单地放置setViewControllers:direction:animated:completion:主队列中dispatch_async块内的代码为我修复了它.对你来说这看起来像

dispatch_async(dispatch_get_main_queue(), ^{
    [self.pageViewController setViewControllers:@[ [self.storyboard instantiateViewControllerWithIdentifier:_pageStoryBoardIDs[0]] ]
                                     direction:UIPageViewControllerNavigationDirectionReverse
                                     animated:YES completion:nil];
});
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!

  • 小心这个解决方案。它修复了“无效参数不满足”的问题,但引入了“NSInternalInconsistencyException Duplicate states in queue”,这很难重现,但仍然会导致足够的崩溃让用户担心。 (2认同)

Mar*_*chy 8

进入同样的问题.通过在首次加载时在UIPageViewController上显式设置第一个内容控制器来解决它(即:在'viewDidLoad'内).

// create first page
UIViewController* firstContentPageController = [self contentControllerAtIndex: 0];
[_paginationController
    setViewControllers: @[firstContentPageController]
    direction: UIPageViewControllerNavigationDirectionForward
    animated: NO
    completion: nil];
Run Code Online (Sandbox Code Playgroud)

其中'contentControllerAtIndex:'是一个创建内容控制器的简单助手方法.我还在两个委托方法中使用它,以便为给定页面返回适当的控制器.

- (UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
    NSInteger index = (NSInteger)((MyContentController*)viewController).pageIndex;

    return [self contentControllerAtIndex: index - 1];
}


- (UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
    NSInteger index = (NSInteger)((MyContentController*)viewController).pageIndex;

    return [self contentControllerAtIndex: index + 1];
}


- (MyContentController*)contentControllerAtIndex: (NSInteger)index {
    if (index < 0 || _pagesContent.count <= index)
        return nil;

    // create view controller
    MyContentController* contentController = [self.storyboard instantiateViewControllerWithIdentifier: @"MyContentController"];
    contentController.pageIndex = index;
    contentController.content = [_pagesContent objectAtIndex: index];

    return contentController;
}
Run Code Online (Sandbox Code Playgroud)

这样做的原因是UIPageViewControllerDataSource协议被设计为只有拉动上一个/下一个内容控制器的方法,而不是在特定索引处拉动单个控制器.这是一个奇怪的设计决定,但需要注意的是,当首次加载组件时,不必由Cocoa调用,而是必须手动设置其起始状态.笨拙的框架设计恕我直言


小智 5

好吧,这是2018年,错误仍然存​​在。我尝试了上述所有解决方案,但没有一个对我有用。经过多次尝试,将animation参数设置为false,这是我迅速完成的工作4

let myViewController : UIViewController = orderedViewControllers[vcIndex]
setViewControllers([myViewController], direction: .forward, animated: false, completion: nil);
Run Code Online (Sandbox Code Playgroud)

然后,只需设置自定义过渡即可。希望它可以帮助处于相同情况的其他人。


Bin*_*ing 5

我们最近做了一些调查,发现禁用动画可以防止崩溃。但我们仍然希望在切换选项卡时显示动画,因此我们试图找到一种方法来避免动画在可能导致崩溃的状态下发生。这是解决方案:

let vc = self.orderedViewControllers[index]
self.pageViewController.setViewControllers([vc], direction: direction, animated: !self.pageViewController.children.contains(vc), completion:nil)
Run Code Online (Sandbox Code Playgroud)

以下是调查结果:

  1. 使用childViewControllers而不是viewControllers检查屏幕上当前的视图控制器。反映childViewControllers了 上的实际视图控制器UIPageViewController,而 正是viewControllers我们设置的/用户刚刚滑动到的视图控制器,它的计数是 1 或 2。

  2. 可能UIPageViewController会变得陈旧 - 具有两个以上的子视图控制器,并且无法通过用户滑动手势删除它们。调用setViewControllers会重置正确的状态,但如果有动画,它会崩溃。

  3. 我们可以通过在不同选项卡之间快速点击或按住 的同时UIPageViewController快速点击不同选项卡来重现过时状态(成功率更高)。看来复杂的操作会破坏 的内部队列UIPageViewController,并且会抛出以下错误而崩溃:

    NSInternalInconsistencyException:无效参数不满足:[视图数] == 3

  4. 调用setViewControllers回调didFinishAnimating也会导致崩溃。