Masonry如何动态更新约束的优先级(priority)

4,743 阅读2分钟

平时使用Masonry时,一般会使用mas_updateConstraints方法来更新约束,不过该方法只能更新数值,并不会更新约束的优先级。

🌰例如:

@implementation xxx
- (void)setupConstraints {
    [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        ......
        make.right.equalTo(self.view).offset(-50).priorityMedium();
        // 靠左距离50,最高优先级
        make.left.equalTo(self.view).offset(50).priorityHigh(); 
    }];
}

- (void)changePriority:(BOOL)isHigh {
    // 更新靠左距离约束的优先级
    [self.nameLabel mas_updateConstraints:^(MASConstraintMaker *make) {
       if (isHigh) {
           make.left.equalTo(self.view).offset(50).priorityHigh();
       } else {
           make.left.equalTo(self.view).offset(50).priorityLow();
       }
    }];
    // 刷新布局
    [self layoutIfNeeded];
}
@end
  • 测试得知,这样是不能更新约束的优先级的,只会按初始约束来布局。

看看Masonry的源码可以得知:

  • 写着 just update the constant:只更新constant的数值。

不过有一种情况可以更新,就是修改的是同一个约束的优先级:

这种方式其实只是切换了constant,相当于修改了constant的数值。(PS:使用.offset(xxx)也是修改constant的数值)

如何动态更新约束的优先级

方式一:强引用约束

  • 初始化后就立马修改的话(同一个Runloop循环内)并不会有变化,适用于初始化后晚一些再更新的情况。
@interface xxx ()
@property (nonatomic, strong) MASConstraint *constraint;
@end

@implementation xxx

- (void)setupConstraints {
    [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        ......
        self.constraint = make.right.equalTo(self).priorityLow();
    }];
}

- (void)changePriority:(BOOL)isHigh {
    // 让约束失效(内部调用uninstall,从约束组内移除)
    [self.constraint deactivate]; 

    // 重新设置优先级
    if (isHigh) {
        self.constraint.priorityHigh();
    } else {
        self.constraint.priorityLow();
    }

    // 让约束生效(内部调用install,重新添加到约束组内)
    [self.constraint activate]; 

    // 刷新布局
    [self layoutIfNeeded];
}

@end

方式二:弱引用约束【推荐】

  • 相当于重新创建约束(不是全部,重新创建的是想要更新的约束),适用各种情况,能立马更新。
@interface xxx ()
@property (nonatomic, weak) MASConstraint *constraint;
@end

@implementation xxx

- (void)setupConstraints {
    [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        ......
        self.constraint = make.right.equalTo(self).priorityLow();
    }];
}

- (void)changePriority:(BOOL)isHigh {
    // 让约束失效(内部调用uninstall,从约束组内移除,由于当前约束是弱引用,没有被其他指针强引用着则会被系统回收)
    [self.constraint uninstall]; 

    // 重新创建约束(mas_updateConstraints 会把 block 内的约束添加到约束组内并生效)
    [self.nameLabel mas_updateConstraints:^(MASConstraintMaker *make) {
        if (isHigh) {
            self.constraint = make.right.equalTo(self).priorityHigh();
        } else {
            self.constraint = make.right.equalTo(self).priorityLow();
        }
    }];

    // 刷新布局
    [self layoutIfNeeded];
}

@end

Done.