【问题标题】:Can't programmatically set NSLayoutConstraint multiplier in swift... "Cannot assign to the result of this expression无法以编程方式快速设置 NSLayoutConstraint 乘数...“无法分配给此表达式的结果
【发布时间】:2015-03-08 08:42:42
【问题描述】:

我正在尝试以编程方式快速设置乘数的约束,当我设置值时,它只会给我一个错误,“无法分配给这个表达式的结果”...

我用 IBOutlet 声明了 NSLayoutConstraint,然后设置了乘数,就像我对另一个常量所做的一样,效果很好,但是这个不会接受它...

@IBOutlet weak var clockWidthConstraint: NSLayoutConstraint!

override func updateViewConstraints() {
    super.updateViewConstraints()

    confirmTopConstraint.constant = 40.0
    clockWidthConstraint.multiplier = 0.1  // Gives me the error!

    }

有什么想法吗?

【问题讨论】:

标签: ios swift autolayout constraints nslayoutconstraint


【解决方案1】:

是的,是read only:

var multiplier: CGFloat { get } 

您只能在创建时指定乘数。相反,您可以在运行时更改非常量 constant 属性:

var constant: CGFloat

编辑:

这需要一点努力,但要更改不可变属性,您必须创建一个新约束并复制除要更改的属性之外的所有属性。为此,我一直在尝试不同的技术,但目前正在探索这种形式:

let constraint = self.aspectRatioConstraint.with() {
    (inout c:NSLayoutConstraint.Model) in
    c.multiplier = self.aspectRatio }

或在更现实的环境中使用:

var aspectRatio:CGFloat = 1.0 { didSet {

    // remove, update, and add constraint
    self.removeConstraint(self.aspectRatioConstraint)
    self.aspectRatioConstraint = self.aspectRatioConstraint.with() {
        (inout c:NSLayoutConstraint.Model) in
        c.multiplier = self.aspectRatio }
    self.addConstraint(self.aspectRatioConstraint)
    self.setNeedsLayout()
}}

支持代码在哪里:

extension NSLayoutConstraint {

    class Model {

        init(item view1: UIView, attribute attr1: NSLayoutAttribute,
            relatedBy relation: NSLayoutRelation,
            toItem view2: UIView?, attribute attr2: NSLayoutAttribute,
            multiplier: CGFloat, constant c: CGFloat,
            priority:UILayoutPriority = 1000) {
                self.firstItem = view1
                self.firstAttribute = attr1
                self.relation = relation
                self.secondItem = view2
                self.secondAttribute = attr2
                self.multiplier = multiplier
                self.constant = c
                self.priority = priority
        }

        var firstItem:UIView
        var firstAttribute:NSLayoutAttribute
        var relation:NSLayoutRelation
        var secondItem:UIView?
        var secondAttribute:NSLayoutAttribute
        var multiplier:CGFloat = 1.0
        var constant:CGFloat = 0
        var priority:UILayoutPriority = 1000
    }


    func priority(priority:UILayoutPriority) -> NSLayoutConstraint {
        self.priority = priority;
        return self
    }

    func with(configure:(inout Model)->()) -> NSLayoutConstraint {

        // build and configure model
        var m = Model(
            item: self.firstItem as! UIView, attribute: self.firstAttribute,
            relatedBy: self.relation,
            toItem: self.secondItem as? UIView, attribute: self.secondAttribute,
            multiplier: self.multiplier, constant: self.constant)
        configure(&m)

        // build and return contraint from model
        var constraint = NSLayoutConstraint(
            item: m.firstItem, attribute: m.firstAttribute,
            relatedBy: m.relation,
            toItem: m.secondItem, attribute: m.secondAttribute,
            multiplier: m.multiplier, constant: m.constant)
        return constraint
    }
}

【讨论】:

  • 嗯,我遇到了一个问题,我试图让 iPhone 4s 布局适合屏幕上的所有内容,所以我使用等宽约束使图像足够小以使用乘数适合所有内容,但我想让它们在其他设备上更大,因为它们可以更大并且完美地适合所有东西......那么还有其他方法可以解决这个问题吗?也许我可以设置两个相等的宽度约束并简单地禁用一个,然后启用另一个?
  • 你能评论一下你是如何做到这一点的吗?
  • 并且对于多个设置,您可以设置多个具有交错优先级的约束。 Autolayout 随机选择一个约束来打破冲突,因此我将可选的约束保持在自己的优先级上,首先是我想要的,然后是回退。一般来说,可以这么说,您还需要硬 (1000) 边界约束来将事物保持在竞争环境中。
  • 您的示例给了我错误“无法在 .with() 上使用 '(()_->_)' 类型的参数列表调用 'with'
  • @paul:我确实在我的快速 sn-p 中遗漏了一些东西 - 请参阅上面的真实示例。 Swift 强制你为 inout 参数声明显式类型,如果我更喜欢这种形式而不是传入一个因此在本地修改 (var) 并返回的模型,我不会这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-15
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多