【问题标题】:'NSInternalInconsistencyException', reason: 'Unexpected subviews' possibly in UIPageViewController (swift, iOS)'NSInternalInconsistencyException',原因:'Unexpected subviews' 可能在 UIPageViewController (swift, iOS)
【发布时间】:2017-11-05 19:45:36
【问题描述】:

过去几个小时我一直坚持这个问题,似乎无法在任何地方找到解决方案。在我的 UIPageViewController 子类显示的第一个视图控制器上滑动后,应用程序崩溃并出现异常 'NSInternalInconsistencyException', reason: 'Unexpected subviews'。我真的不明白这意味着什么以及我应该如何修复错误。调用栈如下:

0   CoreFoundation                      0x00000001123561ab __exceptionPreprocess + 171
1   libobjc.A.dylib                     0x00000001119ebf41 objc_exception_throw + 48
2   CoreFoundation                      0x000000011235b372 +[NSException raise:format:arguments:] + 98
3   Foundation                          0x0000000111490089 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
4   UIKit                               0x000000011565c2e1 -[_UIQueuingScrollView _setWrappedViewAtIndex:withView:] + 377
5   UIKit                               0x000000011565ca09 -[_UIQueuingScrollView _replaceViews:updatingContents:adjustContentInsets:animated:] + 734
6   UIKit                               0x000000011565d00f -[_UIQueuingScrollView _viewAtIndex:loadingIfNecessary:updatingContents:animated:] + 379
7   UIKit                               0x0000000115660664 __54-[_UIQueuingScrollView _didScrollWithAnimation:force:]_block_invoke + 109
8   UIKit                               0x00000001156602e8 -[_UIQueuingScrollView _didScrollWithAnimation:force:] + 534
9   UIKit                               0x000000011565b9f3 -[_UIQueuingScrollView layoutSubviews] + 179
10  UIKit                               0x0000000114c746f5 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1439
11  QuartzCore                          0x0000000117f483ee -[CALayer layoutSublayers] + 153
12  QuartzCore                          0x0000000117f4c4dd _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 401
13  QuartzCore                          0x0000000117ed4ded _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 365
14  QuartzCore                          0x0000000117f00704 _ZN2CA11Transaction6commitEv + 500
15  QuartzCore                          0x0000000117f01450 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 76
16  CoreFoundation                      0x00000001122f8d37 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
17  CoreFoundation                      0x00000001122f8c8e __CFRunLoopDoObservers + 430
18  CoreFoundation                      0x00000001122dc9db CFRunLoopRunSpecific + 443
19  GraphicsServices                    0x000000011780c9c6 GSEventRunModal + 62
20  UIKit                               0x0000000114ba35e8 UIApplicationMain + 159
21  ExponentiallyMe                     0x000000010f891167 main + 55
22  libdyld.dylib                       0x0000000113b54d81 start + 1
23  ???                                 0x0000000000000002 0x0 + 2

从外观上看,调用[_UIQueuingScrollView _setWrappedViewAtIndex:withView:] + 377 中抛出了错误,我不知道为什么。下面也是viewDidLoad()的代码和UIPageViewControllerDataSource协议的两个必需方法。

viewDidLoad()

override func viewDidLoad() {
    super.viewDidLoad()

    self.dataSource = self
    self.delegate = self

    self.activityIndicator("Loading Survey.")

    self.pageControl.frame = CGRect()
    self.pageControl.currentPageIndicatorTintColor = UIColor.white
    self.pageControl.pageIndicatorTintColor = UIColor.lightGray
    self.pageControl.currentPage = 0
    self.view.addSubview(self.pageControl)

    self.pageControl.translatesAutoresizingMaskIntoConstraints = false
    self.pageControl.bottomAnchor.constraint(equalTo: self.view.topAnchor, constant: -20).isActive = true
    self.pageControl.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: -20).isActive = true
    self.pageControl.heightAnchor.constraint(equalToConstant: 20).isActive = true
    self.pageControl.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true

    if self.selectedSurveyType == EMSurveyType.EMST_VISA {
        self.pageControl.numberOfPages = 12
    } else {
        self.pageControl.numberOfPages = 2
    }


    setViewControllers([self.instructionView], direction: .forward, animated: true, completion: nil)
}

UIPageViewControllerDataSource 协议方法

// Get the previous ViewController
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
    guard self.currentPageIndex - 1 > 0 else {
        if self.currentPageIndex - 1 == 0 {
            self.currentPageIndex = 0
            return self.instructionView
        } else {
            return nil
        }
    }
    self.currentPageIndex -= 1
    return self.questionViewControllerAtIndex(self.currentPageIndex - 1)
}

// Get the next ViewController
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
    guard self.currentPageIndex + 1 <= self.questionCount else {
        if self.currentPageIndex == self.questionCount {
            self.currentPageIndex = self.questionCount + 1
            return completionView
        } else {
            return nil
        }
    }
    self.currentPageIndex += 1
    return self.questionViewControllerAtIndex(self.currentPageIndex - 1)
}

子类 UIPageViewController 从 UIViewController 在 UITabBarController 中以模态方式呈现也可能会有所帮助。此外,questionViewControllers 是在函数中创建的:

func questionViewControllerAtIndex(_ index: Int) -> UIViewController {
    let storyboard = UIStoryboard(name:"Main", bundle: nil)
    let qVC = storyboard.instantiateViewController(withIdentifier: "EMSQuestionViewController") as! EMSurveyQuestionViewController
    qVC.questionProperties(questionStatement: self.mainSurveyQuestions[index], subStatements: self.subStatementsForSurveyQuestions[index])
    return qVC
}

非常感谢您,我对此非常迷茫,不明白是什么导致了这些问题。非常感谢任何帮助或“指向我的正确方向”,如果您需要任何进一步的信息/代码,请告诉我。

【问题讨论】:

    标签: ios swift uipageviewcontroller


    【解决方案1】:

    所以对于以后阅读这篇文章的人来说,我似乎已经解决了它。我不太确定这种方法是如何工作的,但不是前一种方法(如果有人能启发我,那就太好了),但似乎试图跟踪当前页面索引并动态创建视图控制器并没有工作。我重写了viewDidLoad() 以创建一个数组allPages,它预先保存了所有页面。然后在这两个协议方法中,我不是检查self.currentPageIndex 的当前位置,而是根据传递的viewController 实例评估当前索引,并使用allPages.index(of: viewController)allPages 数组中检查索引。基于该值,我检查然后通过将 index 的值增加或减少 1 来传递所需的视图控制器。例如对于前一个,返回基于return allPages[index! - 1]。我希望这可能对将来遇到这个问题的人有所帮助,如果有人能告诉我为什么这是有效的,但不是我以前的方法,那也很好。

    【讨论】:

    • “似乎试图跟踪当前页面索引并动态创建视图控制器不起作用”因为您无法知道何时调用数据源方法。页面视图控制器会提前缓存,因此当第 2 页是当前页面时,可能会要求您提供第 4 页。这就是为什么您必须只查看数据源询问的页面。
    【解决方案2】:

    如果您的页面视图控制器呈现了另一个视图控制器,就会发生这种情况。

    一个简单的解决方法是简单地关闭 viewWillDisappear 中任何可能出现的视图控制器:

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        searchController?.dismiss(animated: true, completion: nil)
    }
    

    【讨论】:

    • 这也适用于键盘。view.endEditing(true) 将关闭键盘,从而防止崩溃。
    【解决方案3】:

    在我的情况下,在代码中找到了这部分。

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        "name_of_the_viewcontroller".searchController?.dismiss(animated: true, completion: nil)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-25
      • 2020-06-13
      • 2015-03-06
      • 1970-01-01
      相关资源
      最近更新 更多