12

我正在构建一个复杂的项目,除其他外,我需要将 UIPageViewController 设置为主视图的子视图。我正在使用自动布局,并使用约束对主视图上的各种元素进行排序。

问题是,当我尝试运行应用程序时,由于 NSAutoresizingMaskLayoutConstraints 冲突,它会崩溃。

2013-10-28 16:22:18.419 Red Event App[1658:60b] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
"<NSLayoutConstraint:0x145c1990 V:|-(20)-[UINavigationBar:0x145bf6b0]   (Names: '|':UIView:0x145bf620 )>",
"<NSLayoutConstraint:0x145bf510 V:[UINavigationBar:0x145bf6b0]-(0)-[UIView:0x145bef70]>",
"<NSLayoutConstraint:0x145d0550 UIView:0x145a8c10.top == UIView:0x145bf620.top>",
"<NSAutoresizingMaskLayoutConstraint:0x145b3a40 h=-&- v=-&- UIView:0x145a8c10.midY == UIView:0x145bef70.midY + 56.5>",
"<NSAutoresizingMaskLayoutConstraint:0x145b3a70 h=-&- v=-&- UIView:0x145a8c10.height == UIView:0x145bef70.height + 113>"
)

通常的解决方法是将 TranslatesAutoresizingMaskIntoConstraints 设置为 no。

但是,当我这样做时,UIPageViewController 的子视图开始忽略 PageViewController 的边界,最终(据我所知)原点为 (0,0)。

在设置数据源(_itemViewControllers)时,我尝试通过手动设置框架来固定位置:

- (void)setupLeafs{
    _itemViewControllers = [[NSMutableArray alloc]init];
    for(NSString *pagename in _datasource){
        RWNode *page = [_xml getPage:pagename];
        UIViewController *viewController = [RWNavigationController getViewControllerFromDictionary:[page getDictionaryFromNode]];
        viewController.view.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width, self.view.frame.size.height);

       [_itemViewControllers addObject:viewController];
   }
}

并且在获取页面时

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
    UIViewController *nextViewController = [self getPreviousLeaf:viewController];
    nextViewController.view.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width, self.view.frame.size.height);
    return nextViewController;
}

但两者都没有任何效果。

我需要限制我正在做的事情,所以坚持使用 Masks 不是一种选择。我认为我正在寻找的是一种在添加 UIPageViewController 子项后(通过任何进程调用viewControllerBeforeViewController)对它们施加约束的方法。但我真的很想听听任何可以解决这个问题的方法。

编辑: 我找到了解决问题的方法。我不太确定我在这里列出的是否是整个解决方案,但这是我现在注意到的,经过一个多月的修改代码。

首先,在设置 pageviewcontroller 的视图控制器中,在初始化 pageviewcontroller 之后,我有以下两行

UIView *pageView = self.pageViewController.view; 
pageView.frame = self.view.frame;

不是我[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];在这个视图控制器中设置的。

其次,在子控制器上,我检查视图是在 pageviewcontroller 内部还是外部使用。仅当视图在页面视图控制器中使用时才[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];在子视图上设置。

现在,这目前(对我来说)有效。但我真的很想要一个不那么老套的解决方案。

4

4 回答 4

7

使用 AutoLayout 时,永远不要直接设置视图的框架。约束用于为您执行此操作。通常,如果您想在视图中设置自己的约束,您可以覆盖updateConstraintsUIViews 的方法。确保页面控制器的内容视图允许调整其边缘的大小,因为它们的大小将适合页面视图的框架。您的约束和视图设置需要考虑到这一点,否则您将遇到无法满足的约束错误。

于 2013-12-15T19:35:19.573 回答
4

虽然我不确切知道您要在视觉上实现什么,但这里有两条建议可能会对您有所帮助:

UIView首先,请记住在代码中添加新约束之前从 a 中删除所有现有约束。不要将 Interface Builder 的约束与代码中的约束混为一谈,这会让你发疯。例子:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // remove all constraints
    [self.view removeConstraints:self.view.constraints];

    // add new constraints
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[webView]|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:@{@"webView": self.webView}]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[webView]|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:@{@"webView": self.webView}]];
}

其次,您可以拥有NSLayoutConstraint插座,就像 XIB 或 Storyboard 中的任何其他插座一样。这样,您可以在运行时调整约束的某些属性:

// in your header:
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *myConstraint;

// somewhere in your code where you need to adjust the constraint:
self.myConstraint.constant = 100;

我希望这会有所帮助:)

于 2013-12-17T14:15:28.787 回答
2

我不能给你答案,但也许我可以给你一些调试建议.. 将日志信息复制到文本编辑器中,并用有意义的名称替换视图的内存地址信息。(如果您无法弄清楚,请使用调试器查找内存地址映射到的属性)。然后你会发现更容易理解日志信息和跟踪冲突。这是一个示例(尽管我只是在猜测您的视图层次结构)

"<NSLayoutConstraint:0x145c1990 V:|-(20)-[UINavigationBar:NAVBAR]   (Names: '|':UIView:ROOTVIEW )>",
"<NSLayoutConstraint:0x145bf510 V:[UINavigationBar:NAVBAR]-(0)-[UIView:PAGECONTAINER]>",
"<NSLayoutConstraint:0x145d0550 UIView:PAGEVIEW.top == UIView:ROOTVIEW.top>",
"<NSAutoresizingMaskLayoutConstraint:0x145b3a40 h=-&- v=-&- UIView:PAGEVIEW.midY == UIView:PAGECONTAINER.midY + 56.5>",
"<NSAutoresizingMaskLayoutConstraint:0x145b3a70 h=-&- v=-&- UIView:PAGEVIEW.height == UIView:PAGECONTAINER.height + 113>"

猜测一下,最后两个 autoresizingmasklayoutconstraints 对我来说看起来很奇怪,它们看起来并没有明确定义。

于 2013-12-13T17:20:40.453 回答
1

我刚刚遇到了类似的情况。如果我在 UIPageViewController 的视图上设置任何约束,则会导致与自动调整掩码约束发生冲突。

对我有用的是将 UIPageController 视图的 translatesAutoresizingMaskIntoConstraints 设置为 NO,然后将约束添加到 pageController 视图的顶部、左侧、宽度和高度的父视图。

  self.pageController.view.translatesAutoresizingMaskIntoConstraints = NO;

  NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];
  NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0];
  NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1.0 constant:-60.0];
  NSLayoutConstraint *constraint4 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0];

  [self.view addConstraints:@[constraint1, constraint2, constraint3, constraint4]];
于 2014-03-16T00:51:19.460 回答