简体   繁体   中英

How do I position a subview in UIPageViewController using Auto Layout?

I have a UIPageViewController subclass, and in its viewDidLoad I want to add a UILabel to its self.view . This works fine if I set its position using frames, but if I try to position it using Auto Layout, I get:

* Assertion failure in -[_UIPageViewControllerContentView layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2935.58/UIView.m:8742

How am I supposed to position this UILabel to show up in the UIPageViewController ?

This seems to be happening because UIPageViewController 's view (which is actually a _UIPageViewControllerContentView ) doesn't handle subviews and autolayout as expected (at least in iOS 7; it worked fine for me in iOS 8).

You can get around this by not using autolayout, but I wanted to use autolayout so I ended up redoing my view controllers to avoid adding subviews to UIPageViewController .

Instead of subclassing UIPageViewController , I created a container view controller (a subclass of UIViewController ) with a UIPageViewController as a child view controller. The custom subviews that I initially had in UIPageViewController were then added to the container's view . I also made the container the data source and delegate for the UIPageViewController .

There's a related thread where people got the same assertion failure but with a UITableViewCell : "Auto Layout still required after executing -layoutSubviews" with UITableViewCell subclass . Most of the suggestions there don't work or aren't applicable to UIPageViewController, but it helped me figure out why adding subviews with autolayout might cause a problem.

You can also subclass UIPageViewController and implement this workaround:

#import <objc/runtime.h>

@interface MyPageViewController : UIPageViewController
@end

@implementation MyPageViewController
- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    [self applyLayoutSubviewsWorkaroundIfNeeded];
}

- (void)applyLayoutSubviewsWorkaroundIfNeeded {
    // UIPageViewController does not support AutoLayout in iOS7, we get the following runtime error
    // "_UIPageViewControllerContentView’s implementation of -layoutSubviews needs to call super…"
    // This workaround calls the missing layoutSubviews method of UIView.
    if ([self iOSVersionIsLowerThan8]) {
        IMP uiviewLayoutSubviewsImplementation = class_getMethodImplementation([self.view class], @selector(layoutSubviews));
        typedef void (*FunctionFromImplementation)(id, SEL);
        FunctionFromImplementation uiviewLayoutSubviewsFunction = (FunctionFromImplementation)uiviewLayoutSubviewsImplementation;
        uiviewLayoutSubviewsFunction(self.view, @selector(layoutSubviews));
    }
}

- (BOOL)iOSVersionIsLowerThan8 {
    // This is just one way of checking if we are on iOS7. 
    // You can use whatever method suits you best
    return ![self respondsToSelector(popoverPresentationController)];
}
@end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM