iOS Masonry使用笔记

关于在使用Masonry中遇到的问题

一、约束警告

[LayoutConstraints] Unable to simultaneously satisfy constraints.

Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
****
)
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

上面的问题是由于系统判定代码和编辑器中可能出现了重复约束,可以不做处理,跳过!。

刚开始的时候没有理解重复约束,因为感觉约束的没有毛病。后来才发现,因为cell的高度是根据约束变化,对于固定高度的cell,我约束了某个控件的topleftbottomrightheight,系统判定的原因可能在于已经约束了topbottom,那么对于height就没有必要约束,属于重复约束。

解决办法:设置优先级即可

make.height.mas_equalTo(75).priorityHigh();

关于Masonry中优先级的确定,如下图:

如图中topleftbottomrightheight,我们优先考虑使得此控件所有的约束成立且有效,确保此控件的位置大小。

  • 假设1:只设置topleftbottomright那么这个控件的约束是有问题的,因为父视图没有确定的高度。

  • 假设2:只设置topleftbottomheight,控件的位置就很确定了,所有约束均有效!

由此显而易见,对于此控件而言height的优先级最高。

二、极限值设置greaterThanOrEqualTo 和 lessThanOrEqualTo

使用到的场景还挺多的。举个例子,一个聊天输入框,高度可变,但是需要设置一个最高高度和最低高度。这时候使用这两个属性就很方便了。

greaterThanOrEqualTo大致的意思是约束的内容,不会低于设置的极限值。如:

1. 高度不低于40
make.height.mas_greaterThanOrEqualTo(40);
2. 还可以这样约束
make.left.mas_greaterThanOrEqualTo(self.lastView.mas_right);

lessThanOrEqualTogreaterThanOrEqualTo相反,约束的内容,不会高于设置的极限值

三、单边圆角设置

对于某个使用Masonry约束的控件,设置全角很简单。但是使用Masonry设置单边圆角,总是设置不成功,其实只是需要一个时机,在约束完之后,执行layoutIfNeeded再设置圆角即可!如:

[self.demoView mas_updateConstraints:^(MASConstraintMaker *make) {
    make.left.right.top.bottom.mas_equalTo(self);
}];

// 关键是这句
[self.demoView layoutIfNeeded];

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.demoView.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(5, 5)];// 圆角大小
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.demoView.bounds;
maskLayer.path = maskPath.CGPath;
self.demoView.layer.mask = maskLayer;

四、比例设置

[self.demoView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.left.right.mas_equalTo(self.contentView);
    make.height.mas_equalTo(self.demoView.mas_width).multipliedBy(3/4.);
}];

上面约束意思是高和宽遵循3:4的比例

五、Masonry约束UILabel,多行内容展示不全,显示...

有些情况我们需要UILabel展示多行完整的内容,但是约束没问题,展示效果上偶尔展示完整,偶尔展示不全。如在UITableview中,UILabel的内容首次展示不全,下拉刷新就展示完整了。

搜的结果基本以下两种:

  • 需要设置preferredMaxLayoutWidth,大多数的文章都是这个说法。但实际结果是设置了preferredMaxLayoutWidth,UILabel内容还是展示不全

  • 还有就是设置setContentCompressionResistancePriority:forAxis:,这种说法比较少

但实际运行中,将这两种方式配合起来,发现还是展示不全。

正确的解决办法:设置adjustsFontSizeToFitWidth。如:

self.titleLabel.numberOfLines = 0;
self.titleLabel.preferredMaxLayoutWidth = 200;
[self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
self.titleLabel.adjustsFontSizeToFitWidth = YES;

六、约束自定义的tableHeaderView,实现header高度自适应

第一步:设置UITableViewtableHeaderView,并给自定义的tableHeaderView添加宽度约束,这里必须要约束宽度

/// 必须先设置tableHeaderView = headerview
self.tableView.tableHeaderView = self.headerView;
[self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.width.equalTo(self.tableView);
}];

第二步:更新frame并重新设置tableHeaderView

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    OutpatientDepatmentHeaderView *header = (OutpatientDepatmentHeaderView *)self.tableView.tableHeaderView;
    if (!header) {
        return;
    }
    CGSize size = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    if (header.frame.size.height != size.height) {
        CGRect frame = header.frame;
        frame.size.height = size.height;
        header.frame = frame;
        self.tableView.tableHeaderView = header;
    }
}

第二步是很重要的一步,里面的方法只能在viewDidLayoutSubviews,否则会引起tableHeaderView遮挡住第一个cell,进而引发如下报错:

[TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window........

这个报错是由于tableHeaderView遮挡住了cell,执行reloadData引起的。这种情况下被遮挡的cel其实是不可见的,不能reloadData

七、有意思的点

self.demoImageView = [[UIImageView alloc] init];
self.demoImageView.userInteractionEnabled = YES;
[self.view addSubview:self.demoImageView];
                
[self.demoImageView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.mas_equalTo(self.view).offset(7);
    make.left.mas_equalTo(self.view).offset(7);
}];

上面是对图片的约束,发现我没有约束宽高,在加载成功之后,会自动加一个宽高的约束,宽高等于图片真实的size。就想能不能有什么属性或设置可以设置个宽高的最大值?让图片可以显示在可见的控件范围内,后来没找到相关的方法,后来明了!

// 方式一,重点是这种
self.demoImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"demo"]];
        
// 方式二,同一差不多
self.demoImageView = [[UIImageView alloc] init];
self.demoImageView.image = [UIImage imageNamed:@"demo"];

看完这种初始化方式之后瞬间明了,系统自动加宽高理所当然啊,所以按即定的宽自适应高度显示,突然变得不可能了。还是得在设置图片之后,再修改size啊!!!摆脱不了计算的命运!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352

推荐阅读更多精彩内容