9

我有一些麻烦NSLayoutConstraint

如果我尝试constant使用该setConstant:方法进行更改,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)]>

这正是我想要改变的约束。谁能向我解释为什么会这样?


编辑

我刚刚读到NSAutoresizingMaskLayoutConstraints 是自动添加的,如果您设置[self setTranslatesAutoresizingMaskIntoConstraints:NO];.

如果我禁用它,它可以工作。

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

4

2 回答 2

8

如您未包含的日志消息的其余部分所示,您有不想要或不需要的自动调整大小约束。

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

self.translatesAutoresizingMaskIntoConstraints = NO;

虽然如果您在单独的 nib 中创建视图,它的大小是从哪里获得的?它不是已经有大小限制,您可以创建出口吗?

于 2012-12-19T18:01:31.780 回答
1

I have had this problem twice.

I used a technique described in Cocoa Programming for Mac OSX 4th Ed by Hillegass & Preble. The book advises using an NSBox as a view container and switching the views into it using code. The book also includes some handy code for manually resizing the external containing window to hold the view you just switched to.

The first time I tried their technique I got this exception:

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 

Frustratingly enough I had to refactor the UI and in the rebuilt version (which is based on NSDocument rather than a simple window) I struck the same problem again.

If I set translatesAutoResizingConstraints to NO on the sub-views they don't get laid out properly. But those sub-views are complex so its not a solution though because my windows are not laid out. That does stop the exception from being thrown however.

If I turn off AutoLayout on the top level NSDocument based window XIB - then the exception also stops being thrown. But then the layout for the top level elements is wrong, and the box is not sized correctly. This is not so complex that I couldn't manually lay it all out I guess.

The weird thing is on my first version of the UI it works with no throw. The first version has Autolayout set for the top-level view and all the subviews.

I cannot for the life of me find what obscure setting is turned on in one, but not the other. I pasted the exact same code that works in the window version for swapping views into the document based version, and I went thru control by control checking every setting.

My memory of fixing the issue the first time is that I had turned off AutoLayout on the XIB, but looking at it now trying to fix for the second time, the AutoLayout is turned on and it works fine.

First version works - second one doesn't. The only thing I can think of is that somehow something in NSDocument or something else is causing the issue.

However I did find a way to fix it in case number two: turn off the "AutoResizes Subviews" check-box for the NSBox used as a view container.

Why this is not required in the first version of the UI (which works fine with that checkbox set) is a mystery.

Anyway - documented here in case it helps someone else.

于 2013-01-05T13:25:00.243 回答