MasonryExample

纯手写自动布局会有时会让人欲哭无泪。Masonry出现让这一事情简单多了。
Masonry是什么?去问问度娘你就知道了。
下面是开发中几种常用的布局在Masonry中的应用Case.
****Case1:并排label
Case2:动态居中
Case3:百分比高度
Case4:UITableView(主要是cell的自动布局)
Case5:top(bottom)GuideView
Case6:自定义baseline****
话不多说,上代码。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //将ViewController作为UINavigationController对象中
    ViewController *VC=[[ViewController alloc] init];
    UINavigationController *navi=[[UINavigationController alloc] initWithRootViewController:VC];
    self.window.rootViewController=navi;
    return YES;
}

接下来的class:Case1ViewController、Case2ViewController、Case3ViewController、Case4ViewController皆继承自BaseViewController

#import <UIKit/UIKit.h>
#import "Masonry.h"
@interface BaseViewController : UIViewController
@end

接下来分开来看这四种case
Case1:并排label:并排两个label,整体靠左边,宽度随内容增长,左边的lable”优先级更高“

#import "Case1ViewController.h"

@interface Case1ViewController ()

@property(nonatomic,retain) UILabel   *introductionLabel;
@property(nonatomic,retain) UIView    *containView;
@property(nonatomic,retain) UIStepper *leftStepper;
@property(nonatomic,retain) UIStepper *rightStepper;
@property(nonatomic,retain) UILabel   *label1;
@property(nonatomic,retain) UILabel   *label2;

@end

@implementation Case1ViewController
#pragma mark - Life Cycle
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self uiConfig];
}
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}
#pragma mark - Private Method

-(void)uiConfig
{
    [self.view addSubview:self.introductionLabel];
    [self.introductionLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view.mas_centerX);
        make.top.equalTo(self.view.mas_top).offset(100);
        make.width.equalTo(@280);
        make.height.equalTo(@70);
    }];
    [self.view addSubview:self.containView];
    [self.containView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left).offset(10);
        make.right.equalTo(self.view.mas_right).offset(-10);
        make.height.equalTo(@50);
        make.top.equalTo(self.introductionLabel.mas_top).offset(100);
    }];
    //label1、label2
    [self.containView addSubview:self.label1];
    [self.containView addSubview:self.label2];
    //lable1:位于左上角
    [self.label1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.containView.mas_top).offset(5);
        make.left.equalTo(_containView.mas_left).offset(2);
        //高度 45
        make.height.equalTo(@45);
    }];
    //label2:位于右上角
    [_label2 mas_makeConstraints:^(MASConstraintMaker *make) {
        //左边贴着label1
        make.left.equalTo(_label1.mas_right).offset(2);
        //上边贴着父view
        make.top.equalTo(self.containView.mas_top).offset(5);
        //右边的间隔保持大于等于2,注意是lessThanOrEqual
        //这里的“lessThanOrEqual”放在从左往右的X轴上考虑会更好理解
        //即:label2的右边界的X坐标值“小于等于“containView的右边界-2
        make.right.lessThanOrEqualTo(self.containView.mas_right).offset(-2);
        make.height.equalTo(@45);
    }];
    [self.view addSubview:self.leftStepper];
    [self.leftStepper mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left).offset(20);
        make.top.equalTo(_containView.mas_bottom).offset(40);
        make.width.equalTo(@80);
        make.height.equalTo(@50);
    }];
    [self.view addSubview:self.rightStepper];
    [self.rightStepper mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self.view.mas_right).offset(-20);
        make.top.equalTo(_containView.mas_bottom).offset(40);
        make.width.equalTo(@80);
        make.height.equalTo(@50);
    }];
    //设置label1的content hugging 为1000
    [_label1 setContentHuggingPriority:UILayoutPriorityRequired forAxis:
      UILayoutConstraintAxisHorizontal];
    //设置lable1的content compression为1000
    [_label1 setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    //设置label2的content hugging 为1000
    [_label2 setContentHuggingPriority:UILayoutPriorityRequired forAxis:
     UILayoutConstraintAxisHorizontal];
    //设置lable2的content compression为1000
    [_label2 setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];

}
-(void)stepperAction:(UIStepper *)kStepper
{
    switch (kStepper.tag) {
        case 1:
            _label1.text=[self getLabelContentWithCount:(NSInteger)kStepper.value+1];
            break;
        case 2:
            _label2.text=[self getLabelContentWithCount:(NSInteger)kStepper.value+1];
            break;
        default:
            break;
    }
}
-(NSString *)getLabelContentWithCount:(NSInteger)count
{
    NSMutableString *ret=[NSMutableString new];
    for (NSInteger i=0; i<count; i++) {
        [ret appendString:@"label,"];
    }
    return ret;
}
#pragma mark - Setter And Getter
-(UILabel *)introductionLabel
{
    if (_introductionLabel==nil) {
        _introductionLabel=[[UILabel alloc] init];
        _introductionLabel.numberOfLines=0;
        _introductionLabel.text=@"并排两个label,整体靠左边,宽度随内容增长,左边的label‘优先级’更高";
        _introductionLabel.textAlignment=NSTextAlignmentCenter;
        _introductionLabel.textColor=[UIColor blackColor];
    }
    return _introductionLabel;
}

-(UIView *)containView
{
    if (_containView==nil) {
        _containView=[[UIView alloc] init];
        _containView.backgroundColor=[UIColor lightGrayColor];
    }
    return _containView;
}
-(UIStepper *)leftStepper
{
    if (_leftStepper==nil) {
        _leftStepper=[[UIStepper alloc] initWithFrame:CGRectZero];
//        _leftStepper.maximumValue=8;
        _leftStepper.tag=1;
        [_leftStepper addTarget:self action:@selector(stepperAction:) forControlEvents:UIControlEventValueChanged];
    }
    return _leftStepper;
}

-(UIStepper *)rightStepper
{
    if (_rightStepper==nil) {
        _rightStepper=[[UIStepper alloc] initWithFrame:CGRectZero];
        //        _l_rightStepper.maximumValue=8;
        _rightStepper.tag=2;
        [_rightStepper addTarget:self action:@selector(stepperAction:) forControlEvents:UIControlEventValueChanged];
    }
    return _rightStepper;
}
-(UILabel *)label1
{
    if (_label1==nil) {
        _label1=[[UILabel alloc] init];
        _label1.backgroundColor=[UIColor yellowColor];
        _label1.textColor=[UIColor blackColor];
        _label1.text=@"label,";
        _label1.textAlignment=NSTextAlignmentCenter;
    }
    return _label1;
}
-(UILabel *)label2
{
    if (_label2==nil) {
        _label2=[[UILabel alloc] init];
        _label2.backgroundColor=[UIColor redColor];
        _label2.textColor=[UIColor blackColor];
        _label2.text=@"label,";
        _label2.textAlignment=NSTextAlignmentCenter;
    }
    return _label2;
}
@end

Case2:动态居中:四个图标并排显示,隐藏、显示其中任意一个,整体保持居中

#import "Case2ViewController.h"

static const CGFloat IMAGE_SIZE = 32;

@interface Case2ViewController ()

@property(nonatomic,retain) UILabel        *titleLabel;
@property(nonatomic,retain) UIView         *containerView;
@property(nonatomic,retain) NSMutableArray *imageViews;
@property(nonatomic,retain) NSMutableArray *widthConstraints;
@property(nonatomic,retain) NSArray        *imageNames;

@end

@implementation Case2ViewController

#pragma mark - Life Cycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self uiConfig];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

#pragma mark - Private Method

-(void)uiConfig
{
    [self.view addSubview:self.titleLabel];
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view.mas_centerX);
        make.top.equalTo(self.view.mas_top).offset(100);
        make.height.mas_equalTo(60);
        make.width.mas_equalTo(300);
    }];
    [self.view addSubview:self.containerView];
    [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view.mas_centerX);
        make.top.equalTo(self.view.mas_top).offset(200);
        make.height.mas_equalTo(40);
    }];
    UIView *switchContain=[[UIView alloc] init];
    switchContain.backgroundColor=[UIColor lightGrayColor];
    switchContain.alpha=0.2;
    [self.view addSubview:switchContain];
    [switchContain mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view.mas_centerX);
        make.top.equalTo(self.view.mas_top).offset(270);
        make.width.mas_equalTo(270);
        make.height.mas_equalTo(40);
    }];
    for (int i=0; i<4; i++) {
        UISwitch *switchView=[[UISwitch alloc] init];
        switchView.on=YES;
        switchView.tag=10+i;
        [switchView addTarget:self action:@selector(switchValueChanged:) forControlEvents:UIControlEventValueChanged];
        [self.view addSubview:switchView];
        [switchView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.height.mas_equalTo(40);
            make.width.mas_equalTo(60);
            make.top.equalTo(switchContain.mas_top).offset(5);
            make.left.equalTo(switchContain.mas_left).offset(i*70);
        }];
    }
    [self initImageViews];
}

-(void)initImageViews
{
        //循环创建,添加imageView
    for (int i=0; i<4; i++) {
        UIImageView *imgView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:self.imageNames[i]]];
        [self.imageViews addObject:imgView];
        [self.containerView addSubview:imgView];
    }
        //设定大小
    CGSize imageViewSize=CGSizeMake(IMAGE_SIZE, IMAGE_SIZE);
        //分别设置每个imageView的宽高、左边、垂直中心约束
        //并排排列

//    UIImageView *imageView1 = self.imageViews[0];
//    MASConstraint *width1 = [self setView:imageView1 size:imageViewSize left:self.containerView.mas_left centerY:self.containerView.mas_centerY];
//    [self.widthConstraints addObject:width1];
//    UIImageView *imageView2 = self.imageViews[1];
//    MASConstraint *width2 = [self setView:imageView2 size:imageViewSize left:imageView1.mas_right centerY:self.containerView.mas_centerY];
//    [self.widthConstraints addObject:width2];
//    UIImageView *imageView3 = self.imageViews[2];
//    MASConstraint *width3 = [self setView:imageView3 size:imageViewSize left:imageView2.mas_right centerY:self.containerView.mas_centerY];
//    [self.widthConstraints addObject:width3];
//    UIImageView *imageView4 = self.imageViews[3];
//    MASConstraint *width4 = [self setView:imageView4 size:imageViewSize left:imageView3.mas_right centerY:self.containerView.mas_centerY];
//    [self.widthConstraints addObject:width4];
//        //最后设置最右边的imageView的右边与父view的最右对齐
//    [imageView4 mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.right.equalTo(self.containerView.mas_right);
//    }];
//    
    //或者用下面的方法布局imageView
    UIView *frontView;
    for (int i=0; i<self.imageViews.count; i++) {
        UIImageView *imgView=self.imageViews[i];
        [self.containerView addSubview:imgView];
        MASViewAttribute *left=i==0?self.containerView.mas_left:frontView.mas_right;
        [self.widthConstraints addObject:[self setView:imgView size:imageViewSize left:left centerY:self.containerView.mas_centerY]];
        if (i==self.imageViews.count-1) {
            [imgView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.right.equalTo(self.containerView.mas_right);
            }];
        }
        frontView=imgView;
    }
}


/*!
 *  设置view的宽高、左边约束,垂直中心约束
 *
 *  @param view     要设置的view
 *  @param size     CGSize
 *  @param left     左边对其的约束
 *  @param centerY  水平对齐的约束
 *
 *  @return 返回宽约束,用于显示、隐藏单个view
 */
- (MASConstraint *)setView:(UIView *)view size:(CGSize)size left:(MASViewAttribute *)left centerY:(MASViewAttribute *)centerY
{
    __block MASConstraint *widthConstraint;
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
            //宽高固定
        widthConstraint = make.width.equalTo(@(size.width));
        make.height.equalTo(@(size.height));
            //左边约束
        make.left.equalTo(left);
            //垂直中心对齐
        make.centerY.equalTo(centerY);
    }];
    return widthConstraint;
}

-(void)switchValueChanged:(UISwitch *)kSwitch
{
    NSInteger tag=kSwitch.tag-10;
    MASConstraint *width = self.widthConstraints[tag];
    if (kSwitch.on) {
        width.equalTo(@(IMAGE_SIZE));
    } else {
        width.equalTo(@0);
    }
}

#pragma makr - Setter And Getter


-(UIView *)containerView
{
    if (_containerView==nil) {
        _containerView=[[UIView alloc] init];
        _containerView.backgroundColor=[UIColor lightGrayColor];
    }
    return _containerView;
}


-(NSMutableArray *)imageViews
{
    if (_imageViews==nil) {
        _imageViews=[[NSMutableArray alloc] init];
    }
    return _imageViews;
}

-(NSMutableArray *)widthConstraints
{
    if (_widthConstraints==nil) {
        _widthConstraints=[[NSMutableArray alloc] init];
    }
    return _widthConstraints;
}

-(NSArray *)imageNames
{
    if (_imageNames==nil) {
        _imageNames=@[@"bluefaces_1",@"bluefaces_2",@"bluefaces_3",@"bluefaces_4"];
    }
    return _imageNames;
}

-(UILabel *)titleLabel
{
    if (_titleLabel==nil) {
        _titleLabel=[[UILabel alloc] init];
        _titleLabel.textColor=[UIColor blackColor];
        _titleLabel.numberOfLines=0;
        _titleLabel.lineBreakMode=NSLineBreakByWordWrapping;
        _titleLabel.textAlignment=NSTextAlignmentCenter;
        _titleLabel.text=@"四个图标并排显示,隐藏、显示其中任意一个,整体保持居中。";
    }
    return _titleLabel;
}

@end

Case3:百分比宽度:子View的宽度始终是父View宽度的一半

#import "Case3ViewController.h"

static const CGFloat MAXWIDTH = 300;

@interface Case3ViewController ()

@property(nonatomic,retain) UILabel            *kTitleLable;
@property(nonatomic,retain) UISlider            *kSlider;
@property(nonatomic,retain) UIView             *containerView;

@end

@implementation Case3ViewController

#pragma mark - Life Cycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self uiConfig];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

#pragma mark - Private Method

-(void)uiConfig
{
    [self.view addSubview:self.kTitleLable];
    [self.kTitleLable mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.mas_equalTo(300);
        make.height.mas_equalTo(40);
        make.top.equalTo(self.view.mas_top).offset(100);
        make.centerX.equalTo(self.view.mas_centerX);
    }];
    [self.view addSubview:self.containerView];
    [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.kTitleLable.mas_left);
        make.width.mas_equalTo(MAXWIDTH);
        make.top.equalTo(self.kTitleLable.mas_bottom).offset(40);
        make.height.mas_equalTo(60);
    }];
    UIView *subView=[[UIView alloc] init];
    subView.backgroundColor=[UIColor blueColor];
    [self.containerView addSubview:subView];
    [subView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.containerView.mas_left);
        make.bottom.equalTo(self.containerView.mas_bottom);
        make.top.equalTo(self.containerView.mas_top);
        make.width.equalTo(self.containerView.mas_width).multipliedBy(0.5);
    }];
    [self.view addSubview:self.kSlider];
    [self.kSlider mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.containerView.mas_left);
        make.right.equalTo(self.kTitleLable.mas_right);
        make.top.equalTo(self.containerView.mas_bottom).offset(40);
        make.height.mas_equalTo(40);
    }];
}

#pragma mark - Action

-(void)kSliderAction:(UISlider *)mSlider
{
    if (mSlider.value) {
        [self.containerView mas_updateConstraints:^(MASConstraintMaker *make) {
            make.width.mas_equalTo(MAXWIDTH*mSlider.value);
        }];
    }
}

#pragma mark - Setter And Getter

-(UISlider *)kSlider
{
    if (_kSlider==nil) {
        _kSlider=[[UISlider alloc] initWithFrame:CGRectZero];
        [_kSlider setValue:1];
        [_kSlider addTarget:self action:@selector(kSliderAction:) forControlEvents:UIControlEventValueChanged];
    }
    return _kSlider;
}

-(UIView *)containerView
{
    if (_containerView==nil) {
        _containerView=[[UIView alloc] init];
        _containerView.backgroundColor=[UIColor lightGrayColor];
        _containerView.alpha=0.3;
    }
    return _containerView;
}

-(UILabel *)kTitleLable
{
    if (_kTitleLable==nil) {
        _kTitleLable=[[UILabel alloc] init];
        _kTitleLable.textColor=[UIColor blackColor];
        _kTitleLable.textAlignment=NSTextAlignmentCenter;
        _kTitleLable.text=@"子View的宽度始终是父View宽度的一半";
        _kTitleLable.numberOfLines=0;
        _kTitleLable.lineBreakMode=NSLineBreakByWordWrapping;
    }
    return _kTitleLable;
}

@end

Case4:UITableView(主要是cell的自动布局):变高的cell+简单的高度缓存
方法1、调用systemLayoutSizeFittingSize:获取高度。
方法2、使用iOS8的Self-Sizing特性。

Case4ViewController中的代码如下:

#import "Case4ViewController.h"
#import "Case4CustomCell.h"
#import "Case4Model.h"


#define  kIOS8    [UIDevice currentDevice].systemVersion.floatValue>=8.0

@interface Case4ViewController () <UITableViewDataSource,UITableViewDelegate>

@property(nonatomic,retain)  UITableView    *kTableView;
@property(nonatomic,retain)  NSMutableArray *kDataSource;
@property(nonatomic,retain)  UILabel        *kTitleLabel;

@end

@implementation Case4ViewController

#pragma mark - Life Cycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view addSubview:self.kTitleLabel];
    [self.kTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view.mas_centerX);
        make.width.mas_equalTo(300);
        make.top.equalTo(self.view.mas_top).offset(64);
        make.height.mas_equalTo(80);
    }];
    [self.view addSubview:self.kTableView];
    [self loadData];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

#pragma mark - UITableViewDataSource

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.kDataSource.count;
}


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    Case4CustomCell *cell=[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([Case4CustomCell class]) forIndexPath:indexPath];
    [cell setDataModel:[self.kDataSource objectAtIndex:indexPath.row]];
    return cell;
}

#pragma mark - UITableViewDelegate

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
        //
    if (kIOS8) {
        return UITableViewAutomaticDimension;
    }else{
    static Case4CustomCell *templeCell;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        templeCell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([Case4CustomCell class])];
    });
        // 获取对应的数据
    Case4Model *model = self.kDataSource[indexPath.row];
        // 填充数据
    [templeCell setDataModel:model];
        // 判断高度是否已经计算过
    if (model.kHeight <= 0) {
            // 根据当前数据,计算Cell的高度,注意+1
        model.kHeight = [templeCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1;
        NSLog(@"Calculate height: %ld", (long) indexPath.row);
    } else {
        NSLog(@"Get cache %ld", (long) indexPath.row);
        NSLog(@"height=%f",model.kHeight);
    }
    return model.kHeight;
    }
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

#pragma mark - Private Method

-(void)loadData
{
    for (int i=0; i<15; i++) {
        Case4Model *model=[[Case4Model alloc] init];
        model.kImgName=[NSString stringWithFormat:@"bluefaces_%d",arc4random()%4+1];
        model.kTitle=[NSString stringWithFormat:@"row:%d",i];
        model.kContent=[self getTextWithCount:i];
        [self.kDataSource addObject:model];
    }
    [self.kTableView reloadData];
}

-(NSString *)getTextWithCount:(int)count
{
    NSMutableString *tempStr=[[NSMutableString alloc] init];
    while (count>0) {
        [tempStr appendString:@"试问谁可,洁白无比。天空是什么颜色,你就是什么颜色。当潮流爱新鲜。"];
        count-=1;
    }
    return tempStr;
}

#pragma mark - Setter And Getter

-(UITableView *)kTableView
{
    if (_kTableView==nil) {
        _kTableView=[[UITableView alloc] initWithFrame:CGRectMake(0,64+80+10, self.view.frame.size.width, self.view.frame.size.height-64-80-10) style:UITableViewStylePlain];
        _kTableView.tableFooterView=[UIView new];
        _kTableView.dataSource=self;
        _kTableView.delegate=self;
        if (kIOS8) {
            _kTableView.estimatedRowHeight=60;
            _kTableView.rowHeight=UITableViewAutomaticDimension;
        }
        [_kTableView registerClass:[Case4CustomCell class] forCellReuseIdentifier:NSStringFromClass([Case4CustomCell class])];
    }
    return _kTableView;
}

-(NSMutableArray *)kDataSource
{
    if (_kDataSource==nil) {
        _kDataSource=[[NSMutableArray alloc] init];
    }
    return _kDataSource;
}

-(UILabel *)kTitleLabel
{
    if (_kTitleLabel==nil) {
        _kTitleLabel=[[UILabel alloc] init];
        _kTitleLabel.numberOfLines=0;
        _kTitleLabel.backgroundColor=[UIColor orangeColor];
        _kTitleLabel.textAlignment=NSTextAlignmentCenter;
        _kTitleLabel.textColor=[UIColor blackColor];
        _kTitleLabel.text=@"变高的cell+简单的高度缓存 方法1:调用systemLayoutSizeFittingSize:获取高度。方法2:使用iOS8的Self-Sizing特性";
    }
    return _kTitleLabel;
}

@end

Case4CustomCell中的代码如下:

#import "Case4CustomCell.h"
#import "Masonry.h"

static  NSString *cellId=@"Case4CustomCell";

@interface Case4CustomCell ()

@property(nonatomic,retain)  UIImageView *avatarView;
@property(nonatomic,retain)  UILabel     *kTitleLabel;
@property(nonatomic,retain)  UILabel     *contentLabel;


@end

@implementation Case4CustomCell

//重写初始化方法
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self=[super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (self) {
        [self uiconfig];
    }
    return self;
}


#pragma mark - Public Method

-(void)setDataModel:(Case4Model *)kModel
{
    NSString *imgName=kModel.kImgName;
    self.avatarView.image=[UIImage imageNamed:imgName];
    self.kTitleLabel.text=kModel.kTitle;
    self.contentLabel.text=kModel.kContent;
}

#pragma mark - Private Method

-(void)uiconfig
{

    [self.contentView addSubview:self.avatarView];
    [self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.and.height.equalTo(@40);
        make.left.and.top.equalTo(self.contentView).with.offset(4);
    }];

    [self.contentView addSubview:self.kTitleLabel];
    [self.kTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@15);
        make.top.equalTo(self.contentView).with.offset(4);
        make.left.equalTo(_avatarView.mas_right).with.offset(4);
        make.right.equalTo(self.contentView).with.offset(-4);
    }];

    CGFloat preferredMaxWidth = [UIScreen mainScreen].bounds.size.width - 44-10;
        // Content - 多行
    self.contentLabel.preferredMaxLayoutWidth = preferredMaxWidth; // 多行时必须设置
    [self.contentView addSubview:self.contentLabel];
    [self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_kTitleLabel.mas_bottom).with.offset(4);
        make.left.equalTo(_avatarView.mas_right).with.offset(4);
        make.right.equalTo(self.contentView).with.offset(-4);
        make.bottom.equalTo(self.contentView).with.offset(-4);
    }];
    [_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
}

#pragma mark - Setter And Getter

-(UIImageView *)avatarView
{
    if (_avatarView==nil) {
        _avatarView=[[UIImageView alloc] initWithFrame:CGRectZero];
        _avatarView.layer.masksToBounds=YES;
        _avatarView.layer.cornerRadius=20;
    }
    return _avatarView;
}

-(UILabel *)kTitleLabel
{
    //单行
    if (_kTitleLabel==nil) {
        _kTitleLabel=[[UILabel alloc] init];
    }
    return _kTitleLabel;
}

-(UILabel *)contentLabel
{
    if (_contentLabel==nil) {
        _contentLabel=[[UILabel alloc] initWithFrame:CGRectZero];
        _contentLabel.numberOfLines=0;
        _contentLabel.textColor=[UIColor lightGrayColor];
        _contentLabel.font=[UIFont systemFontOfSize:14];
        _contentLabel.lineBreakMode=NSLineBreakByWordWrapping;
    }
    return _contentLabel;
}

@end

Case4Model:如下

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface Case4Model : NSObject

@property(nonatomic,copy)   NSString *kTitle;
@property(nonatomic,copy)   NSString *kContent;
@property(nonatomic,copy)   NSString  *kImgName;
//保存计算过的高度
@property(nonatomic,assign) CGFloat   kHeight;

@end

Case4:UITableView(主要是cell的自动布局):变高的cell+简单的高度缓存 情况二(和上一个差不多,只是补充了一个个人在一种出现的问题的解决方案)*

#import "ViewController.h"
#import "ViewControllerCell.h"
#import "ViewControllerModel.h"


#define kIOS8  [[UIDevice currentDevice] systemVersion].floatValue>7.0

@interface ViewController () <UITableViewDataSource,UITableViewDelegate>

@property(nonatomic,retain) UITableView    *kTableView;
@property(nonatomic,retain) NSMutableArray *kDataSource;

@end

@implementation ViewController

#pragma mark - Life Cycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self uiConfig];
    [self loadData];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

#pragma mark - UITableViewDataSource

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.kDataSource.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ViewControllerCell *cell=[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([ViewControllerCell class]) forIndexPath:indexPath];
    ViewControllerModel *model=[self.kDataSource objectAtIndex:indexPath.row];
    [cell setDataModel:model];
    return cell;
}

#pragma mark - UITableViewDelegate

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (kIOS8) {
        _kTableView.rowHeight=UITableViewAutomaticDimension;
    }
    static ViewControllerCell *templeCell;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        templeCell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([ViewControllerCell class])];
    });
        // 获取对应的数据
    ViewControllerModel *model = self.kDataSource[indexPath.row];
        // 填充数据
    [templeCell setDataModel:model];
        // 判断高度是否已经计算过
    if (model.kHeight <= 0) {
            // 根据当前数据,计算Cell的高度,注意+1
        model.kHeight = [templeCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1;
        NSLog(@"Calculate height: %ld", (long) indexPath.row);
    } else {
        NSLog(@"Get cache %ld", (long) indexPath.row);
        NSLog(@"height=%f",model.kHeight);
    }
    return model.kHeight;
}

#pragma mark - Private Method

-(void)uiConfig
{
    self.view.backgroundColor=[UIColor whiteColor];
    [self.view addSubview:self.kTableView];
}

-(void)loadData
{
    for (int i=0; i<20; i++) {
        ViewControllerModel *model=[[ViewControllerModel alloc] init];
        model.kTitle=[NSString stringWithFormat:@"row:%d",i];
        model.kContent=[self getTextWithCount:arc4random()%20];
        model.kImgName=[NSString stringWithFormat:@"bluefaces_%d",arc4random()%4+1];
        [self.kDataSource addObject:model];
    }
    [self.kTableView reloadData];
}

-(NSString *)getTextWithCount:(int)kCount
{
    NSMutableString *tempStr=[[NSMutableString alloc] init];
    while (kCount>=0) {
        [tempStr appendString:@"试问谁可,洁白无比"];
        kCount-=1;
    }
    return tempStr;
}

#pragma mark - Setter And Getter

-(UITableView *)kTableView
{
    if (_kTableView==nil) {
        _kTableView=[[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
        _kTableView.dataSource=self;
        _kTableView.delegate=self;
        if (kIOS8) {
            _kTableView.estimatedRowHeight=60;
            _kTableView.rowHeight=UITableViewAutomaticDimension;
        }
        [_kTableView registerClass:[ViewControllerCell class] forCellReuseIdentifier:NSStringFromClass([ViewControllerCell class])];
        _kTableView.tableFooterView=[UIView new];
    }
    return _kTableView;
}

-(NSMutableArray *)kDataSource
{
    if (_kDataSource==nil) {
        _kDataSource=[[NSMutableArray alloc] init];
    }
    return _kDataSource;
}

@end

model如下:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface ViewControllerModel : NSObject

@property(nonatomic,copy)   NSString *kContent;
@property(nonatomic,copy)   NSString *kTitle;
@property(nonatomic,copy)   NSString *kImgName;

    //简单的高度缓存
@property(nonatomic,assign) CGFloat kHeight;

@end

cell:如下

#import "ViewControllerCell.h"
#import "Masonry.h"

@interface ViewControllerCell ()

@property(nonatomic,retain) UILabel     *kContentLabel;
@property(nonatomic,retain) UIImageView *avatarView;
@property(nonatomic,retain) UILabel     *kTitleLabel;

@end

@implementation ViewControllerCell

-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self uiConfig];
    }
    return self;
}

-(void)setDataModel:(ViewControllerModel *)kModel
{
    UIImage *img=[UIImage imageNamed:kModel.kImgName];
    self.avatarView.image=img;
    self.kContentLabel.text=kModel.kContent;
    self.kTitleLabel.text=kModel.kTitle;
}

#pragma mark - Private Method

-(void)uiConfig
{
        //在使用Masonry布局的时候 与cell的关系一定要写成self.contentView  别问我为什么,我不会告诉你是惨痛的教训
    [self.contentView addSubview:self.kContentLabel];
    [self.kContentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.contentView.mas_top).offset(4);
        make.left.equalTo(self.contentView.mas_left).offset(10);
        make.right.equalTo(self.contentView.mas_right).offset(-10);
    }];
    [self.kContentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    [self.contentView addSubview:self.avatarView];
    [self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.mas_equalTo(40);
        make.height.mas_equalTo(40);
        make.left.equalTo(self.mas_left).offset(10);
        make.top.equalTo(self.kContentLabel.mas_bottom).offset(4);
        make.bottom.lessThanOrEqualTo(self.contentView.mas_bottom).offset(2);
    }];
    [self.contentView addSubview:self.kTitleLabel];
    [self.kTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.contentView.mas_centerX);
        make.width.mas_equalTo(100);
        make.height.mas_equalTo(21);
        make.bottom.equalTo(self.contentView.mas_bottom).offset(-5);
    }];
}

#pragma mark - Setter And Getter

-(UILabel *)kContentLabel
{
    if (_kContentLabel==nil) {
        _kContentLabel=[[UILabel alloc] initWithFrame:CGRectZero];
        _kContentLabel.font=[UIFont systemFontOfSize:16];
        _kContentLabel.textColor=[UIColor lightGrayColor];
        _kContentLabel.numberOfLines=0;
        _kContentLabel.lineBreakMode=NSLineBreakByWordWrapping;
        CGFloat maxWidth=[UIScreen mainScreen].bounds.size.width-30;
        _kContentLabel.preferredMaxLayoutWidth=maxWidth;
    }
    return _kContentLabel;
}

-(UIImageView *)avatarView
{
    if (_avatarView==nil) {
        _avatarView=[[UIImageView alloc] initWithFrame:CGRectZero];
        _avatarView.layer.masksToBounds=YES;
        _avatarView.layer.cornerRadius=20;
    }
    return _avatarView;
}

-(UILabel *)kTitleLabel
{
    if (_kTitleLabel==nil) {
        _kTitleLabel=[[UILabel alloc] initWithFrame:CGRectZero];
        _kTitleLabel.font=[UIFont systemFontOfSize:16];
    }
    return _kTitleLabel;
}

@end

Case5:top(bottom)GuideView:使用top(bottom)LayoutGuide确定当前ViewController的最佳显示范围
方法1:直接使用length属性,避免强制转换成UIView所带来的风险。
方法2:使用新的mas_topLayoutGuide和mas_bottomLayoutGuide

#import "Case5ViewController.h"

#define NEW_METHOD 1

@interface Case5ViewController ()

@property(nonatomic,retain)  UILabel  *kTitleLabel;
@property(nonatomic,retain)  UILabel  *kMethod1Label;
@property(nonatomic,retain)  UILabel  *kMethod2Label;
@property(nonatomic,retain)  UIButton *kBtn1;//show or hide NavigationBar
@property(nonatomic,retain)  UIButton *kBtn2;//show or hide ToolBar
@property(nonatomic,retain)  UIView   *kTopView;
@property(nonatomic,retain)  UIView   *kBottomView;

@end

@implementation Case5ViewController

#pragma mark - Life Cycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self uiConfig];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

#pragma mark - Override

-(void)updateViewConstraints
{

#ifdef NEW_METHOD
        //根据新的length值更新约束
    [_kTopView mas_updateConstraints:^(MASConstraintMaker *make) {
            //直接利用其length属性,避免ios、SDK版本升级后topoLayouGuide不再是UIView
        make.top.equalTo(self.view.mas_top).offset(self.topLayoutGuide.length);
    }];
        // 根据新的length值更新约束
    [_kBottomView mas_updateConstraints:^(MASConstraintMaker *make) {
            // 直接利用其length属性,避免iOS、SDK版本升级后topLayoutGuide不再是UIView
        make.bottom.equalTo(self.view.mas_bottom).with.offset(-(self.bottomLayoutGuide.length));
    }];
#endif
    [super updateViewConstraints];
}

#pragma mark - Private Method

-(void)uiConfig
{
    [self.view addSubview:self.kTitleLabel];
    [self configLabel:self.kTitleLabel withTag:0];
    [self.view addSubview:self.kMethod1Label];
    [self configLabel:self.kMethod1Label withTag:1];
    [self.view addSubview:self.kMethod2Label];
    [self configLabel:self.kMethod2Label withTag:2];

    [self.view addSubview:self.kBtn1];
    [self configButton:self.kBtn1 withTag:11];
    [self.view addSubview:self.kBtn2];
    [self configButton:self.kBtn2 withTag:12];

    [self.view addSubview:self.kTopView];
    [self.kTopView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.mas_equalTo(40);
        make.left.and.right.equalTo(self.view);

#ifdef NEW_METHOD
        make.top.equalTo(self.mas_topLayoutGuide);
#endif
        [self.view addSubview:self.kBottomView];
        [self.kBottomView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.height.mas_equalTo(40);
            make.left.and.right.equalTo(self.view);

#ifdef NEW_METHOD
            make.bottom.equalTo(self.mas_bottomLayoutGuide);
#endif
        }];

    }];
}

-(void)configLabel:(UILabel *)newLabel withTag:(NSInteger)tag
{
    newLabel.textAlignment=NSTextAlignmentCenter;
    newLabel.textColor=[UIColor lightGrayColor];
    newLabel.numberOfLines=0;
    [newLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left).offset(20);
        make.right.equalTo(self.view.mas_right).offset(-20);
        make.top.equalTo(self.view.mas_top).offset(80+tag*45);
    }];
    [newLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    [newLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
}

-(void)configButton:(UIButton *)kBtn withTag:(NSInteger)tag
{
    kBtn.tag=tag;
    NSInteger number=tag-10;
    [kBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [kBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateHighlighted];
    [kBtn addTarget:self action:@selector(kBtnAction:) forControlEvents:UIControlEventTouchUpInside];
    [kBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).offset(300+number*60);
        make.height.mas_equalTo(20);
        make.centerX.equalTo(self.view.mas_centerX);
    }];
    [kBtn setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [kBtn setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
}

-(void)kBtnAction:(UIButton *)mBtn
{
    if (mBtn.tag==11) {
        [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES];
    }else{
        [self.navigationController setToolbarHidden:!self.navigationController.toolbarHidden animated:YES];
    }
    [self updateViewConstraints];
}

#pragma mark - Setter And Getter

-(UILabel *)kTitleLabel
{
    if (_kTitleLabel==nil) {
        _kTitleLabel=[[UILabel alloc] initWithFrame:CGRectZero];
        _kTitleLabel.text=@"使用top(bottom)LayoutGuide确定当前ViewController的最佳显示范围";
    }
    return _kTitleLabel;
}

-(UILabel *)kMethod1Label
{
    if (_kMethod1Label==nil) {
        _kMethod1Label=[[UILabel alloc] initWithFrame:CGRectZero];
        _kMethod1Label.text=@"方法1:直接使用length属性,避免强制转换成UIView所带来的风险。";
    }
    return _kMethod1Label;
}

-(UILabel *)kMethod2Label
{
    if (_kMethod2Label==nil) {
        _kMethod2Label=[[UILabel alloc] initWithFrame:CGRectZero];
        _kMethod2Label.text=@"方法2:使用新的mas_topLayoutGuide和mas_bottomLayoutGuide";
    }
    return _kMethod2Label;
}

-(UIButton *)kBtn1
{
    if (_kBtn1==nil) {
        _kBtn1=[UIButton buttonWithType:UIButtonTypeCustom];
        [_kBtn1 setTitle:@"show or hide NavigationBar" forState:UIControlStateNormal];
    }
    return _kBtn1;
}

-(UIButton *)kBtn2
{
    if (_kBtn2==nil) {
        _kBtn2=[UIButton buttonWithType:UIButtonTypeCustom];
        [_kBtn2 setTitle:@"show or hide ToolBar" forState:UIControlStateNormal];
    }
    return _kBtn2;
}

-(UIView *)kTopView
{
    if (_kTopView==nil) {
        _kTopView=[[UIView alloc] init];
        _kTopView.backgroundColor=[UIColor orangeColor];
    }
    return _kTopView;
}

-(UIView *)kBottomView
{
    if (_kBottomView==nil) {
        _kBottomView=[[UIView alloc] init];
        _kBottomView.backgroundColor=[UIColor brownColor];
    }
    return _kBottomView;
}

@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值