@IBDesignable,NSLayoutConstraint用于superview的比例乘数宽度?

时间:2021-07-14 22:47:13

In an @IBDesignable,

在@IBDesignable中,

I'm trying to programmatically set "width 20% of parent":

我正在尝试以编程方式设置“父级的宽度20%”:

@IBDesignable
class TwentyPercentExample:UIView {

    func setup() {
        let cWidth = NSLayoutConstraint(
            item: self,
            attribute: NSLayoutAttribute.width,
            relatedBy: NSLayoutRelation.equal,
            toItem: self.superview,
            attribute: NSLayoutAttribute.width,
            multiplier: 0.2,
            constant:0
        )
        addConstraint(cWidth)
        print("I seemed to added the width constraint....")
        updateConstraintsIfNeeded() // could be useful..
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.setup()
    }

}

(So, you'd add a UIView in storyboard, perhaps set it anchored on the left to the superview, and then change the class to TwentyPercentExample.)

(所以,你要在故事板中添加一个UIView,或者将它固定在左边的superview上,然后将类更改为TwentyPercentExample。)

Strangely this doesn't work. if you do this:

奇怪的是,这不起作用。如果你这样做:

multiplier: 1,
constant:100

it nicely sets it, in realtime, in storyboard to 100 width. Change to

它很好地将它设置为实时,在故事板中达到100宽度。改成

multiplier: 1,
constant:200

and it works fine, changes it in realtime to 200 width. However this just doesn't seem to work:

它工作正常,实时更改为200宽度。然而,这似乎不起作用:

multiplier: 0.2,
constant:0

Do I have toItem: wrong, or something? What's the deal?

我有toItem:错误,还是什么?这是怎么回事?

1 个解决方案

#1


2  

I suspect the problem is that you're doing this in init when self.superview is nil. You should wait to add the constraint until after its been added to the superview. Perhaps in didMoveToSuperview(), though this could get messy since you'll need to account for the fact that it could be added to a superview more than once.

我怀疑问题是你在self.superview为零时在init中执行此操作。您应该等待添加约束,直到将其添加到超级视图中。也许在didMoveToSuperview()中,虽然这可能会变得混乱,因为你需要考虑它可以不止一次添加到超级视图的事实。

Probably the reason the fixed constant case works is because its legal to have a constraint that's hardcoded to 100 with a nil item as the toItem: argument.

固定常量情况可能起作用的原因可能是因为它的合法性有一个约束,硬编码为100,其中nil项为toItem:参数。


So, either of these

所以,其中任何一个

override func didMoveToSuperview() { setup() }
... or ...
override func layoutSubviews() { setup() }

func setup() {
    self.widthAnchor
      .constraint(equalTo: superview!.widthAnchor, multiplier: 0.2)
      .isActive = true
}

seem to work: but seems to work irregularly and generate "agent crashed" errors in Xcode.

似乎工作:但似乎不规则地工作,并在Xcode中生成“代理崩溃”错误。

#1


2  

I suspect the problem is that you're doing this in init when self.superview is nil. You should wait to add the constraint until after its been added to the superview. Perhaps in didMoveToSuperview(), though this could get messy since you'll need to account for the fact that it could be added to a superview more than once.

我怀疑问题是你在self.superview为零时在init中执行此操作。您应该等待添加约束,直到将其添加到超级视图中。也许在didMoveToSuperview()中,虽然这可能会变得混乱,因为你需要考虑它可以不止一次添加到超级视图的事实。

Probably the reason the fixed constant case works is because its legal to have a constraint that's hardcoded to 100 with a nil item as the toItem: argument.

固定常量情况可能起作用的原因可能是因为它的合法性有一个约束,硬编码为100,其中nil项为toItem:参数。


So, either of these

所以,其中任何一个

override func didMoveToSuperview() { setup() }
... or ...
override func layoutSubviews() { setup() }

func setup() {
    self.widthAnchor
      .constraint(equalTo: superview!.widthAnchor, multiplier: 0.2)
      .isActive = true
}

seem to work: but seems to work irregularly and generate "agent crashed" errors in Xcode.

似乎工作:但似乎不规则地工作,并在Xcode中生成“代理崩溃”错误。