2012-12-19 60 views
9

我在NSLayoutConstraint中遇到了一些问题。通过代码添加和设置NSLayoutConstraint

如果我试图使用setConstant:方法尝试更改constant,NSLayoutConstraint给了我一个例外。当我通过代码添加高度约束时,我只有这个问题。

首先,我得到了高度约束,像这样:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstAttribute = %d", NSLayoutAttributeWidth]; 
NSArray *filteredArray = [[self constraints] filteredArrayUsingPredicate:predicate]; 
return filteredArray[0]; 

这给了我正确的约束。我有一个NSTextField子类,它可以很好地工作。约束在Interface Builder中设置,我可以设置和修改常量。

现在我有了一个视图,我在运行时添加了不同的子视图。 这些子视图位于自己的NIB中,这意味着我无法固定它们的宽度和高度。 所以我认为只要将视图添加到超级视图中就会添加约束条件。 正在执行viewDidMoveToSuperview

// Pin Width & Height 
[self addConstraint:[NSLayoutConstraint constraintWithItem:self 
          attribute:NSLayoutAttributeWidth 
          relatedBy:NSLayoutRelationEqual 
           toItem:nil 
          attribute:NSLayoutAttributeNotAnAttribute 
          multiplier:1.0f 
           constant:self.frame.size.width]]; 
[self addConstraint:[NSLayoutConstraint constraintWithItem:self 
               attribute:NSLayoutAttributeHeight 
               relatedBy:NSLayoutRelationEqual 
                toItem:nil 
               attribute:NSLayoutAttributeNotAnAttribute 
               multiplier:1.0f 
                constant:self.frame.size.height]]; 

约束被添加,我可以用NSLog来证实这一点。

"<NSLayoutConstraint:0x100605cc0 H:[ITControlPanelChildView:0x100616eb0(269)]>", 
"<NSLayoutConstraint:0x100614410 V:[ITControlPanelChildView:0x100616eb0(317)]>" 

现在,终于,当我尝试使用[constraint setConstant:somethingDifferent];改变约束我得到以下异常:

Unable to simultaneously satisfy constraints: 
(
    "<NSLayoutConstraint:0x10192fcb0 V:[ITControlPanelChildView:0x10192e4f0(100)]>", 
    "<NSAutoresizingMaskLayoutConstraint:0x10053ff10 h=--& v=&-- V:[ITControlPanelChildView:0x10192e4f0(317)]>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x10192fcb0 V:[ITControlPanelChildView:0x10192e4f0(100)]> 

这正是我试图改变约束。 任何人都可以向我解释为什么会发生这种情况?


编辑

我刚才读了NSAutoresizingMaskLayoutConstraint s的自动添加,其中如果设置[self setTranslatesAutoresizingMaskIntoConstraints:NO];可以禁用。

如果我禁用它,它的作品。

更好的是,如果我可以访问创建的NSAutoresizingMaskLayoutConstraint。有谁知道这是如何工作的?

+0

认为您在编写我的答案时添加了该编辑功能! Autolayout是否在子视图的xib中打开?你可以显示你用来添加子视图的代码吗? – jrturton

+0

@jrturton是的,自动布局功能已打开。也许你误会了我的意思,这是行得通的。我只是认为如果我可以使用已经为我创建的'NSAutoresizingMaskLayoutConstraint',而不是禁用它们并自己添加约束条件,那将会很好。你明白我的意思吗? – NSAddict

+0

我有,但你不能。我很惊讶他们提出了Autolayout xib顶层定义的视图,这就是为什么我询问代码的原因。 – jrturton

回答

8

如您未包含的其他日志消息所示,您已获得不需要或不需要的自动调整限制。

您可以在添加子视图时删除这些。在你使用上面的方法,只需要添加这一行:

self.translatesAutoresizingMaskIntoConstraints = NO; 

但如果你正在创建一个单独的笔尖的观点,在那里它得到它的大小?它不是已经有大小限制,你可以创建网点?

1

我有这个问题两次

我使用的技术描述在可可编程为Mac OSX第四版由Hillegass & Preble。本书建议使用NSBox作为视图容器,并使用代码将视图切换到它。本书还包含一些方便的代码,用于手动调整包含外部窗口的大小,以保存您刚切换到的视图。

我第一次尝试了他们的技术,我得到这个异常:

2013-01-05 22:56:05.103 MyApp[17717:303] Unable to simultaneously satisfy constraints: 
(
    "<NSAutoresizingMaskLayoutConstraint:0x100141330 h=--& v=--& H:[NSView:0x10012fdf0(4)]>", 
"<NSLayoutConstraint:0x1001316c0 H:[NSScrollView:0x100123ff0]-(NSSpace(20))-| (Names: '|':NSView:0x10012fdf0)>", 
"<NSLayoutConstraint:0x1001315d0 H:|-(NSSpace(20))-[NSScrollView:0x100123ff0] (Names: '|':NSView:0x10012fdf0)>") 

Will attempt to recover by breaking constraint 

无奈的是我不得不重构UI和重建的版本(这是基于NSDocument,而不是一个简单的窗口)我再次遇到同样的问题。

如果我将子视图上的translatesAutoResizingConstraints设置为NO,则它们不能正确布置。但是这些子视图很复杂,所以它不是解决方案,因为我的窗户没有布置。这确实阻止了抛出的异常。

如果我关闭顶层NSDocument窗口XIB上的AutoLayout - 那么异常也会停止被抛出。但是,然后顶级元素的布局是错误的,并且该框的大小不正确。这并不复杂,我不能手动把它全部放在我猜。

奇怪的是我的第一个版本的UI它没有抛出。第一个版本的Autolayout设置为顶层视图和所有子视图。

我不能为我的生活找到什么隐藏的设置是打开在一个,而不是其他。我粘贴了在窗口版本中工作的完全相同的代码,以便将视图交换到基于文档的版本中,并且我通过控制检查每个设置来进行控制。

我第一次修复问题的记忆是我关闭了XIB上的AutoLayout,但现在正在尝试第二次修复AutoLayout,AutoLayout已打开并且工作正常。

第一版的作品 - 第二版没有。我唯一能想到的就是不知何故NSDocument或其他东西导致了这个问题。

但是我确实找到了解决办法,在第二种情况下:关闭用作视图容器的NSBox的“AutoResizes Subviews”复选框。

为什么这在UI的第一个版本中不需要(与该复选框集合工作正常)是一个谜。

无论如何 - 记录在这里万一它帮助别人。