在swift中使用内联复合表达式
OC是C的超集
在OC中,我们可以使用一种名为内联复合表达式的语法 http://blog.sunnyxx.com/2014/08/02/objc-weird-code/
利用这个特性,我们可以在iOS开发中写复杂的页面布局时,做到类似HTML的标签化的语法.使布局结构和视图层级清晰明了.
举个例子:
有如下布局需求
HTML代码:
<div class="out"> <div class="middle"> <div class="inner"> <p>content1</p> </div> </div> <div class="middle"> <div class="inner"> <p>content2</p> </div> <div class="inner"> <p>content3</p> </div> </div> </div>
可以看出,HTML代码的视图层级关系非常清晰.
使用OC代码布局,但不使用复合内联表达式的写法如下:
UIView *outContainer = [UIView new]; [self.view addSubview:outContainer]; [outContainer mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; UIView *midContainer1 = [UIView new]; [outContainer addSubview:midContainer1]; [midContainer1 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; UILabel *textLabel1 = [UILabel new]; [midContainer1 addSubview:textLabel1]; [textLabel1 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; UIView *midContainer2 = [UIView new]; [outContainer addSubview:midContainer2]; [midContainer2 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; UILabel *textLabel2 = [UILabel new]; [midContainer2 addSubview:textLabel2]; [textLabel2 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; UILabel *textLabel13 = [UILabel new]; [midContainer2 addSubview:textLabel13]; [textLabel13 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }];
虽然完成了布局,但是很不容易从代码看出视图的层级关系,日后维护的时候就不是很方便了.
改用复合内联表达式后的布局代码如下:
UIView *outView = ({ UIView *view = [UIView new]; UIView *midView1 = ({ UIView *view = [UIView new]; UILabel *textLabel = ({ UILabel *label = [UILabel new]; //config your label label; }); [view addSubview:textLabel]; [textLabel mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; view; }); [view addSubview:midView1]; [midView1 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; UIView *midView2 = ({ UIView *view = [UIView new]; UILabel *textLabel1 = ({ UILabel *label = [UILabel new]; //config your label label; }); [view addSubview:textLabel1]; [textLabel1 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; UILabel *textLabel2 = ({ UILabel *label = [UILabel new]; //config your label label; }); [view addSubview:textLabel2]; [textLabel2 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; view; }); [view addSubview:midView2]; [midView2 mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }]; view; }); [self.view addSubview:outView]; [outView mas_makeConstraints:^(MASConstraintMaker *make) { //layout code }];
可以看出层级关系清晰了.并且带来了额外的2个好处:
1.视图之间的耦合度降低了.此时可以复制任意一个内联表达式中包含的代码到其他位置,而不会引起布局错误.
2.不需要绞尽脑汁思考如何命名了,内联复合表达式中的命名因为作用域的关系没有冲突了.
然后我们尝试在swift中也使用复合内联表达式
哦噢,报错了
这说明swift不支持复合内联表达式.bigView在swift中被编译器认为是一个代码块.
但是我们又想使用这种语法带来的好处,怎么办呢?
我们可以利用IIFE来模拟. http://weizhifeng.net/immediately-invoked-function-expression.html
({ let view = UIView() contentView.addSubview(view) view.backgroundColor = .green view.snp.makeConstraints({ (m) in m.edges.equalTo(contentView).inset(UIEdgeInsetsMake(3, 3, 3, 3)) }) ({ let label = UILabel() label.backgroundColor = .red label.textColor = .white self.label = label view.addSubview(label) label.snp.makeConstraints({ (m) in m.center.equalTo(view) }) })() })()
关键在于尾部的括号!