iOS小经验·Masonry布局时因不熟悉Cell生命周期而导致死循环

本文属 iOS小经验系列:累积平时看起来简单,容易忽视的边边角角,各路大佬敬请回避。

设置UICollectionView的footer的时候,可能有新的小伙伴这样写:

问题代码:

  • 头文件
#import 

@interface DownloadCollectionFooter : UICollectionReusableView

/** 标题 */
@property (nonatomic,strong) UIButton * footerBtn;
/** 内存 */
@property (nonatomic,strong) NSString * footerStr;

@end
  • 实现文件
#import "DownloadCollectionFooter.h"
#import "Masonry.h"
@implementation DownloadCollectionFooter

- (instancetype)init
{
    self = [super init];
    if (self) {
         //...
    }
    return self;
}

- (void)layoutSubviews{
    
    [super layoutSubviews];
    _footerBtn = [[UIButton alloc]init];
    [_footerBtn setTitle:@"下载" forState:UIControlStateNormal];
    _footerBtn.titleLabel.font = [UIFont systemFontOfSize:15];
    [self addSubview:_footerBtn];
    
    [_footerBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.mas_left).offset(25);
        make.right.equalTo(self.mas_right).offset(-25);
        make.top.equalTo(self.mas_top).offset(7);
        make.height.mas_equalTo(@36);
    }];
}

问题描述

导致死循环地执行layoutSubviews代码。

问题原因

这是因为,通过Masonry设置约束之前的那个addSubview,会导致layoutSubviews再次执行。那么,如果你在layoutSubviews中设置addSubview,就导致死循环了。

解决方案

  • 在初始化的时候设置Masonry。例如下面初始化的时候调用自定义的initSubViews,然后把原来写在layoutSubviews的问题代码写在initSubViews中去。
-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        [self initSubViews];
    }
    return self;
}

如果你坚持想在layoutSubviews写布局代码,仍然可以,也有个方案:

  • 把addSubview写在初始化方法里面,或者写在子控件的懒加载里面,然后在layoutSubviews的方法里面再用Masonry设置布局约束。

  • 或者,改用frame和bounds等绝对布局方式,addSubview之后,再用绝对布局,并不会 导致layoutSubviews再次执行,例如。

- (void)layoutSubviews{
    
    [super layoutSubviews];
    
    _titleLabel = [[UILabel alloc]init];
    [self addSubview:_titleLabel];
    _titleLabel.frame = CGRectMake(0, 7, SCREEN_WIDTH, 24);
    _titleLabel.centerX = self.centerX;
    _titleLabel.text = @"缓存";
    //等等
}

实验结论

  • layoutSubviews 里面进行 addSubview操作,且通过 Masonry 设置布局,就 导致死循环地执行 layoutSubviews

  • layoutSubviews 里面进行 addSubview操作,且通过 绝对布局 设置布局,并不会 导致死循环地执行 layoutSubviews

  • layoutSubviews 里面 进行 addSubview操作,且通过 Masonry 设置布局,并不会 导致死循环地执行 layoutSubviews

你可能感兴趣的:(iOS小经验·Masonry布局时因不熟悉Cell生命周期而导致死循环)