实时显示iOS编写UI代码效果

移动开发
编写iOS应用UI的方式大概有两种,一种是Storyboard/Xib,另一种是手写代码。采用Storyboard/Xib方式组织UI,由于提供可视化的特性,只要从UI库中拖动UI控件,便可以显示结果,极大地提高开发速度。但面临一个问题就是多人协作开发,由于所有的UI都放在同一个Storyboard文件中,使用Git/SVN合并代码就会出现冲突。多人协作开发还不是主要问题,有人提出可以创建多个Storyboard来分开UI编写,而Storyboard/Xib最主要问题是代码复用性比较差。所以有些人就选择手写UI代码,这样不仅可以解决多人协作开发问题,而且通过自定义控件在多个View使

[[144355]]

编写iOS应用UI的方式大概有两种,一种是Storyboard/Xib,另一种是手写代码。采用Storyboard/Xib方式组织UI,由于提供可视化的特性,只要从UI库中拖动UI控件,便可以显示结果,极大地提高开发速度。但面临一个问题就是多人协作开发,由于所有的UI都放在同一个Storyboard文件中,使用Git/SVN合并代码就会出现冲突。多人协作开发还不是主要问题,有人提出可以创建多个Storyboard来分开UI编写,而Storyboard/Xib最主要问题是代码复用性比较差。所以有些人就选择手写UI代码,这样不仅可以解决多人协作开发问题,而且通过自定义控件在多个View使用。但每次手写UI代码后都要编译、构建和运行,***在模拟器显示,这样会拖慢开发速度。如果每次修改UI控件后,保存修改便实时在模拟器显示修改后结果,就可以极大的提高编写UI的速度。

Live Change.gif

 

Auto Layout

Auto Layout是什么

Auto Layout是一个基于constraint(约束)的布局系统,它根据UI元素之间约束关系来调整UI元素的位置和大小。

Auto Layout解决什么问题

  • 更容易适配不同分辨率设备的屏幕(iPhone 6 Plus, iPhone 6, iPhone 5s/5, iPhone 4s/4)
  • 当设备旋转时不需要做额外处理
  • 使用constraint来描述布局逻辑,更利于理解和清晰

如何使用Auto Layout

Auto Layout中约束的类对应是NSLayoutConstraint, 而创建NSLayoutConstraint对象主要有两种方式,***种是

  1. + (id)constraintWithItem:(id)view1 
  2.                attribute:(NSLayoutAttribute)attribute1 
  3.                relatedBy:(NSLayoutRelation)relation 
  4.                   toItem:(id)view2 
  5.                attribute:(NSLayoutAttribute)attribute2 
  6.               multiplier:(CGFloat)multiplier 
  7.                 constant:(CGFloat)constant; 

上面方法主要意思是,某个view1的attribute1等于(小于或等于/大于或等于)某个view2的attribute2的multiplier倍加上constant。而attribute主要由表示位置(上/下/左/右)和大小(宽/高)的以下几个值:

  1. typedef enum: NSInteger { 
  2.    NSLayoutAttributeLeft = 1
  3.    NSLayoutAttributeRight, 
  4.    NSLayoutAttributeTop, 
  5.    NSLayoutAttributeBottom, 
  6.    NSLayoutAttributeLeading, 
  7.    NSLayoutAttributeTrailing, 
  8.    NSLayoutAttributeWidth, 
  9.    NSLayoutAttributeHeight, 
  10.    NSLayoutAttributeCenterX, 
  11.    NSLayoutAttributeCenterY, 
  12.    NSLayoutAttributeBaseline, 
  13.    NSLayoutAttributeNotAnAttribute = 0 
  14. } NSLayoutAttribute; 

简化一下,使用公式可以表达为:

  1. view1.attribute1 = view2.attribute2 * multiplier + constant 

第二种方式是:

  1. + (NSArray *)constraintsWithVisualFormat:(NSString *)format  
  2.                                  options:(NSLayoutFormatOptions)opts  
  3.                                  metrics:(NSDictionary *)metrics  
  4.                                    views:(NSDictionary *)views; 

这种方式主要是采用Visual Format Language(可视化格式语言)来描述约束布局,虽然语法比较简洁,但是可读性比较差和容易出错。

Auto Layout存在问题

虽然Auto Layout在布局view方面是非常强大和灵活,但是创建constraint的语法过于繁杂,引用Masonry一个例子:

  1. UIView *superview = self; 
  2.  
  3. UIView *view1 = [[UIView alloc] init]; 
  4. view1.translatesAutoresizingMaskIntoConstraints = NO; 
  5. view1.backgroundColor = [UIColor greenColor]; 
  6. [superview addSubview:view1]; 
  7.  
  8. UIEdgeInsets padding = UIEdgeInsetsMake(10101010); 
  9.  
  10. [superview addConstraints:@[ 
  11.  
  12.     //view1 constraints 
  13.     [NSLayoutConstraint constraintWithItem:view1 
  14.                                  attribute:NSLayoutAttributeTop 
  15.                                  relatedBy:NSLayoutRelationEqual 
  16.                                     toItem:superview 
  17.                                  attribute:NSLayoutAttributeTop 
  18.                                 multiplier:1.0 
  19.                                   constant:padding.top], 
  20.  
  21.     [NSLayoutConstraint constraintWithItem:view1 
  22.                                  attribute:NSLayoutAttributeLeft 
  23.                                  relatedBy:NSLayoutRelationEqual 
  24.                                     toItem:superview 
  25.                                  attribute:NSLayoutAttributeLeft 
  26.                                 multiplier:1.0 
  27.                                   constant:padding.left], 
  28.  
  29.     [NSLayoutConstraint constraintWithItem:view1 
  30.                                  attribute:NSLayoutAttributeBottom 
  31.                                  relatedBy:NSLayoutRelationEqual 
  32.                                     toItem:superview 
  33.                                  attribute:NSLayoutAttributeBottom 
  34.                                 multiplier:1.0 
  35.                                   constant:-padding.bottom], 
  36.  
  37.     [NSLayoutConstraint constraintWithItem:view1 
  38.                                  attribute:NSLayoutAttributeRight 
  39.                                  relatedBy:NSLayoutRelationEqual 
  40.                                     toItem:superview 
  41.                                  attribute:NSLayoutAttributeRight 
  42.                                 multiplier:1 
  43.                                   constant:-padding.right], 
  44.  
  45.  ]]; 

如此简单的一个例子都要编写这么多行代码,想象一下如果创建多个view的constraint时会多么痛苦啊。另一个方式是采用Visual Format Language (VFL),虽然语法比较简洁,但是可读性比较差和容易出错。

Masonry

为什么使用Masonry

Masonry是采用链式DSL(Domain-specific language)来封装NSLayoutConstraint,通过这种方式编写Auto Layout布局代码更加易读和简洁。
使用Masonry的MASConstraintMaker来表达相同constraint

  1. UIEdgeInsets padding = UIEdgeInsetsMake(10101010); 
  2.  
  3. [view1 mas_makeConstraints:^(MASConstraintMaker *make) { 
  4.     make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler 
  5.     make.left.equalTo(superview.mas_left).with.offset(padding.left); 
  6.     make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); 
  7.     make.right.equalTo(superview.mas_right).with.offset(-padding.right); 
  8. }]; 

甚至可以更短

  1. [view1 mas_makeConstraints:^(MASConstraintMaker *make) { 
  2.     make.edges.equalTo(superview).with.insets(padding); 
  3. }]; 

#p#

如何使用

使用Masonry创建constraint来定义布局的方式有三种:mas_makeConstraints,mas_updateConstraints,mas_remakeConstraints。

1. mas_makeConstraints

使用mas_makeConstraints创建constraint后,你可以使用局部变量或属性来保存以便下次引用它;如果创建多个constraints,你可以采用数组来保存它们。

  1. // in public/private interface 
  2. @property (nonatomic, strong) MASConstraint *topConstraint; 
  3.  
  4. ... 
  5.  
  6. // when making constraints 
  7. [view1 mas_makeConstraints:^(MASConstraintMaker *make) { 
  8.     self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top); 
  9.     make.left.equalTo(superview.mas_left).with.offset(padding.left); 
  10. }]; 
  11.  
  12. ... 
  13. // then later you can call 
  14. [self.topConstraint uninstall]; 

2. mas_updateConstraints

有时你需要更新constraint(例如,动画和调试)而不是创建固定constraint,可以使用mas_updateConstraints方法

  1. // this is Apple's recommended place for adding/updating constraints 
  2. // this method can get called multiple times in response to setNeedsUpdateConstraints 
  3. // which can be called by UIKit internally or in your code if you need to trigger an update to your constraints 
  4. - (void)updateConstraints { 
  5.     [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) { 
  6.         make.center.equalTo(self); 
  7.         make.width.equalTo(@(self.buttonSize.width)).priorityLow(); 
  8.         make.height.equalTo(@(self.buttonSize.height)).priorityLow(); 
  9.         make.width.lessThanOrEqualTo(self); 
  10.         make.height.lessThanOrEqualTo(self); 
  11.     }]; 
  12.  
  13.     //according to apple super should be called at end of method 
  14.     [super updateConstraints]; 

3. mas_remakeConstraints

mas_remakeConstraints与mas_updateConstraints比较相似,都是更新constraint。不过,mas_remakeConstraints是删除之前constraint,然后再添加新的constraint(适用于移动动画);而mas_updateConstraints只是更新constraint的值。

  1. - (void)changeButtonPosition { 
  2.     [self.button mas_remakeConstraints:^(MASConstraintMaker *make) { 
  3.         make.size.equalTo(self.buttonSize); 
  4.  
  5.         if (topLeft) { 
  6.             make.top.and.left.offset(10); 
  7.         } else { 
  8.             make.bottom.and.right.offset(-10); 
  9.         } 
  10.     }]; 

想了解以上三个代码片段的更多细节,可以下载Masonry iOS Examples工程查阅。

Classy

Classy简介和特性

Classy是一个能与UIKit无缝结合stylesheet(样式)系统。它借鉴CSS的思想,但引入新的语法和命名规则。

灵活内嵌的语法

{ } : ; 这些语法符号是可选的,你可以选择适合自己的风格来表达stylesheet。

你可以使用{ } : ; 来限定stylesheet

  1. $main-color = #e1e1e1; 
  2.  
  3. MYCustomView { 
  4.   background-color: $main-color; 
  5.   title-insets: 510510
  6.   > UIProgressView.tinted { 
  7.     progress-tint-color: black; 
  8.     track-tint-color: yellow; 
  9.   } 
  10.  
  11. ^UIButton.warning, UIView.warning ^UIButton { 
  12.   title-color[state:highlighted]: #e3e3e3; 

或者你使用空格来限定stylesheet

  1. $main-color = #e1e1e1 
  2.  
  3. MYCustomView  
  4.   background-color $main-color 
  5.   title-insets 510510 
  6.   > UIProgressView.tinted  
  7.     progress-tint-color black 
  8.     track-tint-color yellow 
  9.  
  10. ^UIButton.warning, UIView.warning ^UIButton  
  11.   title-color[state:highlighted] #e3e3e3 

默认样式

Classy在应用程序Bundle默认查找文件名为stylesheet.cas的样式文件。如果你采用这个文件名,你可以不用做任何东西就能加载样式文件。
但如果你想指定其他file path(样式文件名),你可以创建[CASStyler defaultStyler]

  1. [CASStyler defaultStyler].filePath = [[NSBundle mainBundle] pathForResource:@"myStyles.cas" ofType:nil]; 

如果你还想当发生错误时,获取错误信息以便于调试,可以使用-(void)setFilePath:error:

  1. NSError *error = nil; 
  2. NSString filePath = [[NSBundle mainBundle] pathForResource:@"myStyles.cas" ofType:nil]; 
  3. [[CASStyler defaultStyler] setFilePath:filePath error:&error]; 

如果你是使用Storyboard/Xib组织UI界面,那就需要在main.m的int main(int argc, char * argv[])方法设置 filePath,这样可以确保在创建UIWindow之前加载stylesheet。否则(采用手写UI代码),你在 AppDelegate.m的- (BOOL)application:didFinishLaunchingWithOptions:方法设置filePath

Live Reload

Live Reload是实时显示编写UI代码效果的关键特性,它能够实时检查stylesheet文件变化,无需重新编译、构建和运行模拟器,从而极大提高开发速度。
为了启用Live Reload,你需要指定stylesheet路径,并且只运行在模拟器上。

  1. #if TARGET_IPHONE_SIMULATOR 
  2.     NSString *absoluteFilePath = CASAbsoluteFilePath(@"../Styles/stylesheet.cas"); 
  3.     [CASStyler defaultStyler].watchFilePath = absoluteFilePath; 
  4. #endif 

Selectors

Style Selectors是指定哪个view使用哪种样式的方式。主要有三种方法来指定目标view:

  1. Object Class
  2. View Hierarchy
  3. Style Class

你可以混合使用三种方法,例子如下:

  1. /* match views 
  2.  * where class is UIButton or UIButton subclass 
  3.  * and styleClass is "large" 
  4.  * and superview class is UITabBar 
  5.  */ 
  6.  
  7. UITabBar > ^UIButton.large { } 

想了解具体如何使用,请查阅官网Selectors章节

为了避免与Objective-C的message selectors混淆,术语style selectors表示Classy stylesheets的selectors

Properties

Classy支持所有UIAppearance的属性和方法,也支持与UIAppearance无关的很多属性。Classy使用与UIKit相同属性命名,所以你不必考虑如何将style property映射到Objective-C的property。
UIPageControl类的属性如下:

  1. @property (nonatomic,retain) UIColor *pageIndicatorTintColor; 
  2. @property (nonatomic,retain) UIColor *currentPageIndicatorTintColor; 

style property的名字采用与objective-c一样的名字

  1. UIPageControl { 
  2.   pageIndicatorTintColor black 
  3.   currentPageIndicatorTintColor purple 

style property的命名规则采用kebab case

  1. UIPageControl { 
  2.   page-indicator-tint-color black 
  3.   current-page-indicator-tint-color purple 

想了解具体如何使用,请查阅官网Properties章节

Keep it DRY(Don't Repeat Yourself)

在编程中一个很重要的原则就是避免重复,这不仅可以大量减少重复代码,并且使得代码更加容易复用和维护。Classy提供三种方式避免代码重复:grouping,nesting,variables

Grouping

如果有两个以上的style selectors共用相同的属性时

  1. UISlider.info { 
  2.   minimum-track-tint-color black 
  3.   maximum-track-tint-color purple 
  4.  
  5. UISlider.error { 
  6.   minimum-track-tint-color black 
  7.   maximum-track-tint-color purple 
  8.   thumb-tint-color red 

我们可以提取相同的属性到分组style selector中

  1. UISlider.info, UISlider.error { 
  2.   minimum-track-tint-color black 
  3.   maximum-track-tint-color purple 
  4.  
  5. UISlider.error { 
  6.   thumb-tint-color red 

#p#

Nesting

如果两个以上style selectors共用相同的view hierarchy时

  1. UICollectionView { 
  2.   background-color #a2a2a2 
  3.  
  4. UICollectionView > UICollectionViewCell { 
  5.   clips-to-bounds NO 
  6.  
  7. UICollectionView > UICollectionViewCell UILabel { 
  8.   text-color purple 
  9.  
  10. UICollectionView > UICollectionViewCell UILabel.title { 
  11.   font 20 

我们通过nesting方式将view hierarchies表达成这样方式

  1. UICollectionView { 
  2.   background-color #a2a2a2 
  3.  
  4.   > UICollectionViewCell { 
  5.     clips-to-bounds NO 
  6.  
  7.     UILabel { 
  8.       text-color purple 
  9.  
  10.       &.title { 
  11.         font 20 
  12.       } 
  13.     } 
  14.   } 

Variables

Classy让你通过定义variables来将多个相同的style property值存储以便共享。Variable命名规则如下:

  • 必须以大小写字母或$符号开头
  • 可以包含_,-或任何字母数字

    1. // prefix with ' $ ' to help distinguish variables 
    2. $brand-color = #e1e1e1 
    3.  
    4. // OR not 
    5. insets = 510510 
    6.  
    7. UIButton { 
    8.   background-color $brand-color 
    9.   contentEdgeInsets insets 
    10.   background-image[state:selected] bg_button insets 

    ***官方还提供一个实例来解释具体如何使用:Custom Views Example

ClassyLiveLayout

ClassyLiveLayout通过结合Classy stylesheets与Masonry一起使用,能够在运行的模拟器中微调Auto Layout约束实时显示效果的工具。

ClassyLiveLayout一个核心category:UIView+ClassyLayoutProperties,在UIView定义以下属性:

  1. @property(nonatomic, assign) UIEdgeInsets cas_margin; 
  2. @property(nonatomic, assign) CGSize cas_size; 
  3.  
  4. // shorthand properties for setting only a single constant value 
  5. @property(nonatomic, assign) CGFloat cas_sizeWidth; 
  6. @property(nonatomic, assign) CGFloat cas_sizeHeight; 
  7.  
  8. @property(nonatomic, assign) CGFloat cas_marginTop; 
  9. @property(nonatomic, assign) CGFloat cas_marginLeft; 
  10. @property(nonatomic, assign) CGFloat cas_marginBottom; 
  11. @property(nonatomic, assign) CGFloat cas_marginRight; 

cas_margin和cas_size分别表示UI元素的位置和大小,而其余的属性都是对两个属性进一步细分。我们可以从stylesheets中访问style properties来定义constraints布局,做到将数据与代码分离,有利于修改和复用代码。

  1. UIView.blue-box { 
  2.     cas_size: 80 100 
  3.     cas_margin-top: 60 
  4.     cas_margin-left: 50 
  5.  
  6. UIView.red-box { 
  7.     cas_size-width: 120 
  8.     cas_margin-left: 20 

我们可以在updateConstraints或updateViewConstrains定义布局时引用style properties

  1. - (void)updateViewConstraints { 
  2.   [super updateViewConstraints]; 
  3.  
  4.   [_blueBoxView mas_updateConstraints:^(MASConstraintMaker *make) { 
  5.       make.width.equalTo(@(_blueBoxView.cas_size.width)); 
  6.       make.height.equalTo(@(_blueBoxView.cas_size.height)); 
  7.       make.top.equalTo(@(_blueBoxView.cas_margin.top)); 
  8.       make.left.equalTo(@(_blueBoxView.cas_margin.left)); 
  9.   }]; 
  10.  
  11.   [_redBoxView mas_updateConstraints:^(MASConstraintMaker *make) { 
  12.       make.width.equalTo(@(_redBoxView.cas_size.width)); 
  13.       make.height.equalTo(_blueBoxView); 
  14.       make.top.equalTo(_blueBoxView); 
  15.       make.left.equalTo(_blueBoxView.mas_right).with.offset(_redBoxView.cas_margin.left); 
  16.   }]; 

当定义view layouts时,将Auto Layout的constraints都放在stylesheets中实时加载(Live reload)。如果你修改constraints,无需重新编译、构建和运行模拟器便能实时看到修改后的效果。

示例工程

配置工程

由于需要引用Masonry,Classy和ClassyLiveLayout,Podfile配置如下:

  1. pod 'Masonry''~> 0.6.1' 
  2. pod 'Classy''~> 0.2.4' 
  3. pod 'ClassyLiveLayout''~> 0.6.0' 

编写代码

1. 添加stylesheet.cas文件到工程

当安装好Masonry,Classy和ClassyLiveLayout后,***次运行项目会出现没有stylesheet.cas文件错误:

No stylesheet.cas file error.png

No stylesheet.cas file error.png

 

只要向工程添加空的stylesheet.cas文件即可。

Create stylesheet.cas file.png

Create stylesheet.cas file.png

 

2. 创建LiveView类,该类继承SHPAbstractView。

Create LiveView inherit SHPAbstractView.png

Create LiveView inherit SHPAbstractView.png

 

在ViewController创建LiveView对象,然后被self.view引用。

Setup root view in ViewController.png

Setup root view in ViewController.png

 

当编译运行时,在SHPAbstractView.h由于找不到UIView出现编译错误。

SHPAbstractView Compile error.png

SHPAbstractView Compile error.png

 

#p#

只需引入UIKit便可以解决,但运行一下应用程序,出现一下错误:

Must override methods.png

Must override methods.png

 

主要原因是任何自定义UIView继承SHPAbstractView都需要override两个方法:- (void)addSubviews和- (void)defineLayout,我们可以查看SHPAbstractView的源码可知:

SHPAbstractView Source Code .png

SHPAbstractView Source Code .png

 

所以只要在LiveView.m文件覆盖两个方法即可

  1. #pragma mark - Add subviews and define layout 
  2. - (void)addSubviews 
  3.  
  4. - (void)defineLayout 

3. LiveView类设计

LiveView主要由包含redBoxView和blueBoxView两个属性,redBoxView表示红色方块,blueBoxView表示蓝色方块。

  1. #import "SHPAbstractView.h" 
  2.  
  3. @interface LiveView : SHPAbstractView 
  4.  
  5. @property (strong, nonatomic) UIView *redBoxView; 
  6. @property (strong, nonatomic) UIView *blueBoxView; 
  7.  
  8. @end 

4. LiveView类实现

由于SHPAbstractView类如何初始化View已经做了处理,暴露两个接口- (void)addSubviews和-(void)defineLayout分别处理构建view hierarchy和定义布局,子类只要覆盖SHPAbstractView这两个方法就可以创建LiveView了。
但是我们将Auto Layout的constraints都放在stylesheets中实时加载(Live reload),即放在本工程的stylesheet.cas文件,将布局数据和布局代码分离。

  1. UIView.redBox { 
  2.     cas_marginTop 50 
  3.     cas_marginLeft 20 
  4.  
  5.     cas_size 100 100 
  6.  
  7. UIView.blueBox { 
  8.     cas_marginTop 50 
  9.     cas_marginRight -20 
  10.  
  11.     cas_size 100 100 

有了constraints数据后,便可以在代码布局:

  1. @implementation LiveView 
  2.  
  3. #pragma mark - Add subviews and define layout 
  4. - (void)addSubviews 
  5.     self.backgroundColor = [UIColor whiteColor]; 
  6.     [self addSubview:self.redBoxView]; 
  7.     [self addSubview:self.blueBoxView]; 
  8.  
  9. - (void)defineLayout 
  10.     [self.redBoxView mas_updateConstraints:^(MASConstraintMaker* make){ 
  11.         make.top.equalTo(@(self.redBoxView.cas_marginTop)); 
  12.         make.left.equalTo(@(self.redBoxView.cas_marginLeft)); 
  13.         make.width.equalTo(@(self.redBoxView.cas_sizeWidth)); 
  14.         make.height.equalTo(@(self.redBoxView.cas_sizeHeight)); 
  15.     }]; 
  16.  
  17.     [self.blueBoxView mas_updateConstraints:^(MASConstraintMaker *make){ 
  18.         make.top.equalTo(@(self.blueBoxView.cas_marginTop)); 
  19.         make.right.equalTo(@(self.blueBoxView.cas_marginRight)); 
  20.         make.width.equalTo(@(self.blueBoxView.cas_sizeWidth)); 
  21.         make.height.equalTo(@(self.blueBoxView.cas_sizeHeight)); 
  22.     }]; 
  23.  
  24. #pragma mark - Lazy initialization 
  25. - (UIView*)redBoxView 
  26.     if (!_redBoxView) { 
  27.         _redBoxView = [UIView new]; 
  28.         _redBoxView.cas_styleClass = @"redBox"
  29.         _redBoxView.backgroundColor = [UIColor redColor]; 
  30.     } 
  31.  
  32.     return _redBoxView; 
  33.  
  34. - (UIView*)blueBoxView 
  35.     if (!_blueBoxView) { 
  36.         _blueBoxView = [UIView new]; 
  37.         _blueBoxView.cas_styleClass = @"blueBox"
  38.         _blueBoxView.backgroundColor = [UIColor blueColor]; 
  39.     } 
  40.  
  41.     return _blueBoxView; 

5. 模拟器支持Live Reload

为了启用Live Reload,你需要指定stylesheet路径,并且只运行在模拟器上。

Support Live Reload.png

Support Live Reload.png

 

此时效果:

Live Change.gif

 

#p#

6. 分离样式文件

由于有网友提出这样一个问题:如果所有view的样式都放在同一个stylesheet.cas文件,会让stylesheet.cas文件繁杂,并且当多个人协同开发时,不易于合并代码,所以有必要将样式文件分离到多个文件中。

  1. 创建variable.cas文件,并将redBox对应UIView的样式放在variable.cas文件中。

    variable.cas file.png

    variable.cas file.png

     

  2. 在stylesheet.cas样式文件使用@import指令引用variable.cas文件

stylesheet.cas file.png

stylesheet.cas file.png

 

***效果

Live Change 1.gif

Live Change 2.gif

 

示例代码存放地址:LiveAutoLayout

总结

之前手写UI代码每次更改一般都要重新编译、构建和运行模拟器才能看到效果,但结合使用Masonry,Classy和ClassLiveLayout之后,告别这个费时过程,极大地提高开发速度;不仅如此,我们将Auto Layout的constraints都放在stylesheets中实时加载(Live reload),将布局数据和布局代码分离,使得代码更加复用和维护。Classy还提供三种避免重复方法:Grouping, Nestting和Variable,尽可能复用样式数据。
这是本人***次编写技术博客,可能有很多错误和漏洞,希望大家多多指点,也希望这篇文章能够帮助到大家。

责任编辑:倪明 来源: 简书
相关推荐

2012-04-24 23:31:41

iOS

2024-03-15 12:48:50

携程AI

2011-08-22 16:45:58

Windows PhoiOS

2022-09-27 14:32:12

iOSiOS 16苹果

2010-09-09 11:16:06

CSS交互

2021-01-19 12:16:10

CSS前端UI

2009-07-10 13:20:37

Swing容器组件

2010-04-29 17:22:42

UNIX系统

2020-03-17 14:26:18

iOS 14iPhone 9 Pl苹果

2011-06-28 17:21:50

QT UI designer

2009-06-25 14:53:35

自定义UI组件JSF框架

2021-06-03 07:45:25

Rust Git 终端 UI

2012-07-02 12:13:32

明基投影机

2011-07-08 15:08:16

iPhone 图片

2013-12-03 09:34:26

iOS应用开发实践高质量Objectiv

2012-09-06 11:18:17

IBMdw

2012-09-10 10:31:31

IBMdw

2013-07-25 13:43:23

iOS开发学习UIView的Anim

2019-11-08 09:20:57

代码开发工具

2022-12-15 10:52:26

代码开发
点赞
收藏

51CTO技术栈公众号