12

I'm developing a simple UIPageViewController that has two pages. Each page is loaded from a different ViewController with their specific xib files, named PViewController and TViewController.

For PViewController, there are three different views, let's call them A, B, and C. When the application launches, PViewController appears successfully and I can swipe left to see the TViewController, also with no problems. However, when I'm in PViewController and as a response to an event I change the current view A to another view B, then swipe left to go to TViewController, I receive the following exception and the application terminates:

*** Assertion failure in -[_UIQueuingScrollView _setWrappedViewAtIndex:withView:], /SourceCache/UIKit_Sim/UIKit-2935.137/_UIQueuingScrollView.m:338
2014-07-10 13:57:23.389 ***** [2012:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unexpected subviews'
*** First throw call stack:
(
    0   CoreFoundation                      0x01fde1e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x01c418e5 objc_exception_throw + 44
    2   CoreFoundation                      0x01fde048 +[NSException raise:format:arguments:] + 136
    3   Foundation                          0x018214de -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
    4   UIKit                               0x00f3cc14 -[_UIQueuingScrollView _setWrappedViewAtIndex:withView:] + 261
    5   UIKit                               0x00f3d248 -[_UIQueuingScrollView _replaceViews:updatingContents:adjustContentInsets:animated:] + 812
    6   UIKit                               0x00f3d690 -[_UIQueuingScrollView _viewAtIndex:loadingIfNecessary:updatingContents:animated:] + 421
    7   UIKit                               0x00f40c65 __54-[_UIQueuingScrollView _didScrollWithAnimation:force:]_block_invoke + 110
    8   UIKit                               0x00f408de -[_UIQueuingScrollView _didScrollWithAnimation:force:] + 579
    9   UIKit                               0x00f3c452 -[_UIQueuingScrollView layoutSubviews] + 186
    10  UIKit                               0x00970964 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
    11  libobjc.A.dylib                     0x01c5382b -[NSObject performSelector:withObject:] + 70
    12  QuartzCore                          0x04be445a -[CALayer layoutSublayers] + 148
    13  QuartzCore                          0x04bd8244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
    14  QuartzCore                          0x04bd80b0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
    15  QuartzCore                          0x04b3e7fa _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
    16  QuartzCore                          0x04b3fb85 _ZN2CA11Transaction6commitEv + 393
    17  QuartzCore                          0x04b40258 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
    18  CoreFoundation                      0x01fa636e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    19  CoreFoundation                      0x01fa62bf __CFRunLoopDoObservers + 399
    20  CoreFoundation                      0x01f839eb CFRunLoopRunSpecific + 491
    21  CoreFoundation                      0x01f837eb CFRunLoopRunInMode + 123
    22  GraphicsServices                    0x030285ee GSEventRunModal + 192
    23  GraphicsServices                    0x0302842b GSEventRun + 104
    24  UIKit                               0x00901f9b UIApplicationMain + 1225
    25  *******                             0x000239fd main + 141
    26  libdyld.dylib                       0x02cc1701 start + 1
    27  ???                                 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Here is the protocol methods I implemented for the UIPageViewController:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    UIViewController *vc;

    if(self.index==1) {
        vc = (PViewController *)[[PViewController alloc] initWithNibName:@"PViewController" bundle:nil];
    }
    self.index--;


    return vc;
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
    UIViewController *vc;



    if(self.index==0)
        vc = (TViewController *)[[TViewController alloc] initWithNibName:@"TViewController" bundle:nil];

    self.index++;


    return vc;
} //The exception occurs exactly when the app reaches this point.

And this is how I switch views within a view controller, simply:

self.view = self.B; 

Problem:

I'm not able to track down the problem. I don't know where to catch this exception or what is causing it?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
hsnm
  • 658
  • 1
  • 8
  • 20
  • I'm trying to do this exact thing, running into the exact same error. Did you figure out what was causing it? – dfickling Aug 05 '14 at 18:45

5 Answers5

4

I happened to stumble upon the same error when using the following argument passed on launch:

-UIViewShowAlignmentRects YES

After wasting 2 days trying to find error within my UIPageViewController, it turned out that after disabling XCode generated yellow rectangle wrappers, the NSInternalConsistencyException evaporated.

Michael
  • 1,285
  • 18
  • 31
  • 1
    Thank you very much! Unbelievable – Tien Jun 28 '16 at 15:38
  • @Michael, What is `XCode generated yellow rectangle wrappers` ? – Ravi Sisodia Sep 28 '16 at 13:32
  • @rPragma when you add the described argument to your scheme, you will notice that your views start displaying a yellow border that matches their alignment rectangles. – Michael Sep 28 '16 at 13:34
  • So should I set `UIViewShowAlignmentRects` flag to `YES` in schemes (debug and release) ? – Ravi Sisodia Sep 28 '16 at 13:43
  • And I am having similar crash in `production` version, and never got this crash while debugging. – Ravi Sisodia Sep 28 '16 at 13:45
  • @rPragma quite the opposite - you should disable this flag in order to avoid the crash. It's worth noting that the described solution has worked in iOS 9 and I have not had this problem nor tested the solution on iOS 10 – Michael Sep 28 '16 at 13:47
  • So, you are saying that this field is set to yes by Xcode by default ? In any of the scheme, it is not present right now. – Ravi Sisodia Sep 28 '16 at 13:49
  • @rPragma no, what I am saying is that if you are using this flag in your scheme, and are experiencing the described issue, you should try disabling the flag and see if the error is gone :) – Michael Sep 28 '16 at 13:50
  • 1
    Oh. But I'm not using this flag. Thanks anyway. – Ravi Sisodia Sep 28 '16 at 14:00
3

Figured it out (at least what my problem was) - You shouldn't set a UIViewController's self.view directly, but instead use self.view.addSubview(viewA) and then use

UIView.transitionFromView(self.viewA, toView: self.viewB, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromLeft, completion: nil)
dfickling
  • 2,545
  • 2
  • 16
  • 13
3

In my case, this happened when I tried to navigate to the next page view controller inside another view controller that was presented as a modal.

Hopefully this helps other people.

technophyle
  • 7,972
  • 6
  • 29
  • 50
  • 2
    I ran into a similar case. I had an active searchcontroller in my tableview at the moment I wanted to go to the next view controller. A simple dismiss before the transition fixed the issue. – Yannick Winters Jan 31 '17 at 13:05
  • i also have same condition, I presented a modalView with presented Style overCurrentContext. After that when I try to move to next VC of pageVC it crashes. – Prince Kumar Sharma May 10 '17 at 11:00
0

I was having one 'UIPageViewController' in Storyboard and from one of the pages, I was trying to present new 'UINavigationController' with attached 'Rootviewcontroller' which was in separate xib.

When I removed xib and put this view controller as stand alone in storyboard it worked like a charm.

So I think the catch is that if both the container view are in same storyboard then it is not giving any exception or error.

let listView = String(describing: ListViewController.self)
let listViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: listView)
let navigationController = UINavigationController(rootViewController: listViewController)
self.present(navigationController, animated: true, completion: nil)
ZeroOne
  • 584
  • 4
  • 17
-1

I fix this crash with changing direction .forward, to .reverse

pageViewController?.setViewControllers([viewController], direction: direction, animated: true)