Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to add subViews that I want floating in an NSScrollView using AutoLayout?

I have several views that I need to have collaborate with a custom sub-class of NSScrollView I am making. One type of view needs to be fixed completely relative to the scrolling in the NSScrollView and another type needs to have its outer shell fixed in position relative to the scrolling but allow inner contents to scroll as the scrollview changes (like the column headers in a spreadsheet for example).

The following are the options for placement of these views within the view hierarchy AFAIK:

  1. SubView of NSScrollView (makes the most sense but I get the following error: *** +[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:]: A multiplier of 0 or a nil second item together with a location for the first attribute creates an illegal constraint of a location equal to a constant. Location attributes must be specified in pairs)
  2. SubView of the superview of NSScrollView (this seems to work better but doesn't feel right from a design perspective given that I want my views to be part of the scrollView)

===

I have also read in more than one place online that I won't be able to use the Visual Format Language approach to setting up my constraints because floating constraints aren't set relative to the immediate superview. This is the clue that I am doing something wrong above because the 2nd approach could use VCL whereas the first would need to create NSLayoutConstraint manually.

===

The following is the Swift code that I have added to the initialiser of my NSScrollView subclass:

    topCorner = NSButton()
    topCorner.translatesAutoresizingMaskIntoConstraints = false
    topCorner.bezelStyle = NSBezelStyle.CircularBezelStyle  //.RecessedBezelStyle
    topCorner.setButtonType(NSButtonType.PushOnPushOffButton)
    topCorner.identifier = "topCorner"
    topCorner.title = "TC"
    self.addSubview(topCorner)

    thc = NSLayoutConstraint(item: self.topCorner, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.superview, attribute: NSLayoutAttribute.Left, multiplier: 1.0, constant: 0.0)
    self.addConstraint(thc)

    thc1 = NSLayoutConstraint(item: self.topCorner, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 36.0)
    self.addConstraint(thc1)

    thc2 = NSLayoutConstraint(item: self.topCorner, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.superview, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0.0)
    self.addConstraint(thc2)

    thc3 = NSLayoutConstraint(item: self.topCorner, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 24.0)
    self.addConstraint(thc3)

Just to confuse things further, the error message that I get is only when I have the constraints thc and thc2 around in the code. (Experimented with commenting out different constraints to see which was causing the horrible error text.)

like image 277
Sam Avatar asked Dec 30 '14 12:12

Sam


2 Answers

The error message was caused by the fact that the relationship of self.superview had not been created at the time of adding the constraint.

A further error ensues because the two constraints thc & thc2 can't be added to the NSScrollView, they need to be added to its superview.

While the above still does not yield my desired result it gets rid of two errors that have arisen at runtime.

like image 158
Sam Avatar answered Nov 08 '22 08:11

Sam


This will happen if you try to add constraints to views that are not within the view hierachy. An auto layout restriction.

To debug this, I worked out the programmatically created constraint that was causing the issue. Then I debugged to this point and checked neither of the 2 views within the constraint were null when the constraint was added. One of them was. I fixed this and the error went.

like image 42
Charlie Seligman Avatar answered Nov 08 '22 10:11

Charlie Seligman