4
votes

I'm creating an NSTableView inside a NSScrollView programmatically, but when I try to set the frame to the scroll view I'm getting a constraint error.

Unable to simultaneously satisfy constraints:
(
    "<NSAutoresizingMaskLayoutConstraint:0x107d4ec50 h=--& v=--& V:[NSScrollView:0x10068c570(372.5)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x107d4d020 h=-&- v=-&- V:[NSClipView:0x10068d7f0]-(673)-|   (Names: '|':NSScrollView:0x10068c570 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x107d4cfc0 h=-&- v=-&- V:|-(2)-[NSClipView:0x10068d7f0]   (Names: '|':NSScrollView:0x10068c570 )>"
)

Will attempt to recover by breaking constraint 
<NSAutoresizingMaskLayoutConstraint:0x107d4d020 h=-&- v=-&- V:[NSClipView:0x10068d7f0]-(673)-|   (Names: '|':NSScrollView:0x10068c570 )>

Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens.  And/or, break on objc_exception_throw to catch this in the debugger.

It seems like they are being created automatically.

This is my creation code (using arc) I'm subclassing NSView

-(void)addColumnsToTable{
    NSTableColumn *col = [[NSTableColumn alloc]initWithIdentifier:@"priority"];
    [col.headerCell setStringValue:@"priority"];
    [col setWidth:10];
    [col setMinWidth:1];
    [col setMaxWidth:10];
    [self.tableView addTableColumn:col];

   // col = [[NSTableColumn alloc]initWithIdentifier:@"name"];
   // [self.tableView addTableColumn:col];   
}


-(void)createTable{
    NSTableView *tableView = [[NSTableView alloc]initWithFrame:NSZeroRect];

    [tableView setDelegate:self];
    [tableView setDataSource:self];

    NSScrollView *scrollView = [[NSScrollView alloc]initWithFrame:self.bounds];
    [scrollView setBorderType:NSGrooveBorder];

    [self addSubview:scrollView];
    [scrollView setDocumentView:tableView];
    [scrollView setHasVerticalScroller:YES];
    [scrollView setAutohidesScrollers:YES];


    self.tableView = tableView;
    self.scrollView = scrollView;

    [self addColumnsToTable];

}

Here is where it is breaking:

-(void)setFrame:(NSRect)frameRect{
    [super setFrame:frameRect];
    [self.scrollView setFrame:self.bounds];

}

Is there a way to turn off these automatic constraints?

2

2 Answers

7
votes

Got it, the problem is that automatic constraints are being created based on the view's automatic resize mask. To deactivate this behaviour:

[scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];

where scrollView is a subview of NSView

0
votes

I also got the exact same problem when setting the frame of an NSScrollView, within the DrawRect method of a NSView subclass. The above solution of setting the TranslatesAutoresizingMaskIntoConstraints to NO gets rid of the exception. But in my situation, I have a dynamic window. Indeed, my tableview didn’t follow the new frame size I am calculating and setting up to the NSScrollView anymore.

Working around for a while, I finally came up with the right solution. It appear that the problem was not about the NSScrollView autoresizing setup, but setting up the AutoresizesSubviews of my NSView subclass is the right solution for an dynamic custom view.

- (void)awakeFromNib
{

[super awakeFromNib];   
[self setAutoresizesSubviews:NO];   // <- Here is the solution

    // …
}

- (void)drawRect:(NSRect)dirtyRect
{

[super drawRect:dirtyRect];

    // From DirtyRect (dimensions of the my subclass NSView)
    // Calculate the rectangle allowable for MyScrollView
    // and setting local NSRect mRect..

    [MyScrollView setFrame:mRect];      // no more ‘exception’ here
}

I also have to create other NSView subclass programmatically, which also had NSScrollView and frame setting needs. Since those objects have no awakeFromNib method… simply set it elsewhere… like in an Init method of the NSView subclass.

- (id)init:(NSInteger)aSpecialTag
{

[self setAutoresizesSubviews:NO];   // <- Here is the solution

    _mTag = aSpecialTag;

    // …
}