我正在构建一个复杂的项目,除其他外,我需要将UIPageViewController设置为主视图的子视图。我正在使用autolayout,并使用约束来对主视图上的各种元素进行排序。
问题是,当我尝试运行应用程序时,由于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内部还是外部使用。仅当在viewviewcontroller中使用 not 视图时,才会在子视图上设置[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
。
现在,这对我来说很有效。但我真的想要一个不那么黑的解决方案。
答案 0 :(得分:6)
使用AutoLayout时,不应直接设置视图的框架。约束用于为您执行此操作。通常,如果要在视图中设置自己的约束,则可以覆盖UIViews的updateConstraints
方法。确保页面控制器的内容视图允许调整其边缘大小,因为它们的大小将适合页面视图的框架。您的约束和视图设置需要考虑到这一点,否则您将得到不可满足的约束错误。
答案 1 :(得分:4)
虽然我不确切地知道您想要在视觉上实现什么,但这里有两条可能对您有帮助的建议:
首先,请记住在代码中添加新约束之前从UIView
中删除所有现有约束。不要将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或故事板的任何其他出口一样。这样,您可以在运行时调整约束的某些属性:
// in your header:
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *myConstraint;
// somewhere in your code where you need to adjust the constraint:
self.myConstraint.constant = 100;
我希望这有点帮助:)
答案 2 :(得分: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对我来说看起来很奇怪,它们看起来并不清晰。
答案 3 :(得分:1)
我刚遇到类似的情况。如果我在UIPageViewController视图上设置任何约束,它将导致与自动调整遮罩约束冲突。
对我来说有用的是为UIPageController视图设置translatesAutoresizingMaskIntoConstraints为NO,然后为pageController视图的top,left,width和height的父视图添加约束。
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]];