snapkit更新约束崩溃的问题
程序员文章站
2022-06-16 17:40:39
最近在使用snapkit布局时,竟然发现更新约束会导致崩溃,为什么这样呢? 看起来完全没有问题,但是一运行就崩溃,崩溃位置在activeIfNeeded方法中: fatalerror信息提示找不到因存在的constraint来更新,输出existingLayoutConstraints不为nil,输 ......
最近在使用snapkit布局时,竟然发现更新约束会导致崩溃,为什么这样呢?
checkbutton.snp.makeconstraints { (make) in make.left.top.equaltosuperview() make.height.equalto(radiolistsubviewbuttonheight) make.width.equalto(self).multipliedby(0.5) } checkbutton.snp.updateconstraints { (make) in make.width.equalto(self).multipliedby(0.7) }
看起来完全没有问题,但是一运行就崩溃,崩溃位置在activeifneeded方法中:
internal func activateifneeded(updatingexisting: bool = false) { guard let item = self.from.layoutconstraintitem else { print("warning: snapkit failed to get from item from constraint. activate will be a no-op.") return } let layoutconstraints = self.layoutconstraints if updatingexisting { var existinglayoutconstraints: [layoutconstraint] = [] for constraint in item.constraints { existinglayoutconstraints += constraint.layoutconstraints } for layoutconstraint in layoutconstraints { let existinglayoutconstraint = existinglayoutconstraints.first { $0 == layoutconstraint } guard let updatelayoutconstraint = existinglayoutconstraint else { fatalerror("updated constraint could not find existing matching constraint to update: \(layoutconstraint)") } let updatelayoutattribute = (updatelayoutconstraint.secondattribute == .notanattribute) ? updatelayoutconstraint.firstattribute : updatelayoutconstraint.secondattribute updatelayoutconstraint.constant = self.constant.constraintconstanttargetvaluefor(layoutattribute: updatelayoutattribute) } } else { nslayoutconstraint.activate(layoutconstraints) item.add(constraints: [self]) } }
fatalerror信息提示找不到因存在的constraint来更新,输出existinglayoutconstraints不为nil,输出existinglayoutconstraint却为nil,很奇怪。
点击进入first方法,发现是取第一个满足谓词条件的值,而不是简单的取第一个值:
/// returns the first element of the sequence that satisfies the given /// predicate. /// /// the following example uses the `first(where:)` method to find the first /// negative number in an array of integers: /// /// let numbers = [3, 7, 4, -2, 9, -6, 10, 1] /// if let firstnegative = numbers.first(where: { $0 < 0 }) { /// print("the first negative number is \(firstnegative).") /// } /// // prints "the first negative number is -2." /// /// - parameter predicate: a closure that takes an element of the sequence as /// its argument and returns a boolean value indicating whether the /// element is a match. /// - returns: the first element of the sequence that satisfies `predicate`, /// or `nil` if there is no element that satisfies `predicate`. /// /// - complexity: o(*n*), where *n* is the length of the sequence. public func first(where predicate: (element) throws -> bool) rethrows -> element?
在此处谓词条件为 $0 == layoutconstraint ,进入layoutconstraint类中,发现==运算符已被重载:
internal func ==(lhs: layoutconstraint, rhs: layoutconstraint) -> bool { guard lhs.firstitem === rhs.firstitem && lhs.seconditem === rhs.seconditem && lhs.firstattribute == rhs.firstattribute && lhs.secondattribute == rhs.secondattribute && lhs.relation == rhs.relation && lhs.priority == rhs.priority && lhs.multiplier == rhs.multiplier else { return false } return true }
在判断相等时,竟然还判断了multiplier,本例中更新约束前后multiplier不相等,所以找不到对应的约束。
解决方法:
要想修改multiplier,不能使用update,要使用remake