實(shí)時(shí)顯示iOS編寫UI代碼效果(轉(zhuǎn)載)

編寫iOS應(yīng)用UI的方式大概有兩種碑隆,一種是Storyboard/Xib看尼,另一種是手寫代碼。采用Storyboard/Xib方式組織UI弓候,由于提供可視化的特性郎哭,只要從UI庫中拖動(dòng)UI控件,便可以顯示結(jié)果菇存,極大地提高開發(fā)速度夸研。但面臨一個(gè)問題就是多人協(xié)作開發(fā),由于所有的UI都放在同一個(gè)Storyboard文件中依鸥,使用Git/SVN合并代碼就會(huì)出現(xiàn)沖突亥至。多人協(xié)作開發(fā)還不是主要問題,有人提出可以創(chuàng)建多個(gè)Storyboard來分開UI編寫毕籽,而Storyboard/Xib最主要問題是代碼復(fù)用性比較差抬闯。所以有些人就選擇手寫UI代碼,這樣不僅可以解決多人協(xié)作開發(fā)問題关筒,而且通過自定義控件在多個(gè)View使用溶握。但每次手寫UI代碼后都要編譯、構(gòu)建和運(yùn)行蒸播,最后在模擬器顯示睡榆,這樣會(huì)拖慢開發(fā)速度萍肆。如果每次修改UI控件后,保存修改便實(shí)時(shí)在模擬器顯示修改后結(jié)果胀屿,就可以極大的提高編寫UI的速度塘揣。

Live Change.gif

Auto Layout

Auto Layout是什么

Auto Layout是一個(gè)基于constraint(約束)的布局系統(tǒng),它根據(jù)UI元素之間約束關(guān)系來調(diào)整UI元素的位置和大小宿崭。

Auto Layout解決什么問題

更容易適配不同分辨率設(shè)備的屏幕(iPhone 6 Plus, iPhone 6, iPhone 5s/5, iPhone 4s/4)

當(dāng)設(shè)備旋轉(zhuǎn)時(shí)不需要做額外處理

使用constraint來描述布局邏輯亲铡,更利于理解和清晰

如何使用Auto Layout

Auto Layout中約束的類對(duì)應(yīng)是NSLayoutConstraint, 而創(chuàng)建NSLayoutConstraint對(duì)象主要有兩種方式,第一種是

+ (id)constraintWithItem:(id)view1? ? ? ? ? ? ? attribute:(NSLayoutAttribute)attribute1? ? ? ? ? ? ? relatedBy:(NSLayoutRelation)relation? ? ? ? ? ? ? ? ? toItem:(id)view2? ? ? ? ? ? ? attribute:(NSLayoutAttribute)attribute2? ? ? ? ? ? ? multiplier:(CGFloat)multiplier? ? ? ? ? ? ? ? constant:(CGFloat)constant;

上面方法主要意思是葡兑,某個(gè)view1的attribute1等于(小于或等于/大于或等于)某個(gè)view2的attribute2的multiplier倍加上constant奖蔓。而attribute主要由表示位置(上/下/左/右)和大小(寬/高)的以下幾個(gè)值:

typedefenum:NSInteger{NSLayoutAttributeLeft=1,NSLayoutAttributeRight,NSLayoutAttributeTop,NSLayoutAttributeBottom,NSLayoutAttributeLeading,NSLayoutAttributeTrailing,NSLayoutAttributeWidth,NSLayoutAttributeHeight,NSLayoutAttributeCenterX,NSLayoutAttributeCenterY,NSLayoutAttributeBaseline,NSLayoutAttributeNotAnAttribute=0}NSLayoutAttribute;

簡(jiǎn)化一下,使用公式可以表達(dá)為:

view1.attribute1 = view2.attribute2 * multiplier + constant

第二種方式是:

+ (NSArray*)constraintsWithVisualFormat:(NSString*)format? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? options:(NSLayoutFormatOptions)opts? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? metrics:(NSDictionary*)metrics? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? views:(NSDictionary*)views;

這種方式主要是采用Visual Format Language(可視化格式語言)來描述約束布局讹堤,雖然語法比較簡(jiǎn)潔吆鹤,但是可讀性比較差和容易出錯(cuò)。

Auto Layout存在問題

雖然Auto Layout在布局view方面是非常強(qiáng)大和靈活洲守,但是創(chuàng)建constraint的語法過于繁雜疑务,引用Masonry一個(gè)例子:

UIView*superview =self;UIView*view1 = [[UIViewalloc] init];view1.translatesAutoresizingMaskIntoConstraints =NO;view1.backgroundColor = [UIColorgreenColor];[superview addSubview:view1];UIEdgeInsetspadding =UIEdgeInsetsMake(10,10,10,10);[superview addConstraints:@[//view1 constraints[NSLayoutConstraintconstraintWithItem:view1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? attribute:NSLayoutAttributeToprelatedBy:NSLayoutRelationEqualtoItem:superview? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? attribute:NSLayoutAttributeTopmultiplier:1.0constant:padding.top],? ? [NSLayoutConstraintconstraintWithItem:view1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? attribute:NSLayoutAttributeLeftrelatedBy:NSLayoutRelationEqualtoItem:superview? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? attribute:NSLayoutAttributeLeftmultiplier:1.0constant:padding.left],? ? [NSLayoutConstraintconstraintWithItem:view1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? attribute:NSLayoutAttributeBottomrelatedBy:NSLayoutRelationEqualtoItem:superview? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? attribute:NSLayoutAttributeBottommultiplier:1.0constant:-padding.bottom],? ? [NSLayoutConstraintconstraintWithItem:view1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? attribute:NSLayoutAttributeRightrelatedBy:NSLayoutRelationEqualtoItem:superview? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? attribute:NSLayoutAttributeRightmultiplier:1constant:-padding.right], ]];

如此簡(jiǎn)單的一個(gè)例子都要編寫這么多行代碼,想象一下如果創(chuàng)建多個(gè)view的constraint時(shí)會(huì)多么痛苦啊梗醇。另一個(gè)方式是采用Visual Format Language (VFL)知允,雖然語法比較簡(jiǎn)潔,但是可讀性比較差和容易出錯(cuò)婴削。

Masonry

為什么使用Masonry

Masonry是采用鏈?zhǔn)?a target="_blank">DSL(Domain-specific language)來封裝NSLayoutConstraint廊镜,通過這種方式編寫Auto Layout布局代碼更加易讀和簡(jiǎn)潔。

使用Masonry的MASConstraintMaker來表達(dá)相同constraint

UIEdgeInsets padding = UIEdgeInsetsMake(10,10,10,10);[view1 mas_makeConstraints:^(MASConstraintMaker *make) {? ? make.top.equalTo(superview.mas_top).with.offset(padding.top); //withisan optional semantic filler? ? make.left.equalTo(superview.mas_left).with.offset(padding.left);? ? make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);? ? make.right.equalTo(superview.mas_right).with.offset(-padding.right);}];

甚至可以更短

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

如何使用

使用Masonry創(chuàng)建constraint來定義布局的方式有三種:mas_makeConstraints唉俗,mas_updateConstraints嗤朴,mas_remakeConstraints。

1. mas_makeConstraints

使用mas_makeConstraints創(chuàng)建constraint后虫溜,你可以使用局部變量或?qū)傩詠肀4嬉员阆麓我盟㈡ⅲ蝗绻麆?chuàng)建多個(gè)constraints,你可以采用數(shù)組來保存它們衡楞。

// in public/private interface@property(nonatomic,strong) MASConstraint *topConstraint;...// when making constraints[view1 mas_makeConstraints:^(MASConstraintMaker *make) {self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top);? ? make.left.equalTo(superview.mas_left).with.offset(padding.left);}];...// then later you can call[self.topConstraint uninstall];

2. mas_updateConstraints

有時(shí)你需要更新constraint(例如吱雏,動(dòng)畫和調(diào)試)而不是創(chuàng)建固定constraint,可以使用mas_updateConstraints方法

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

3. mas_remakeConstraints

mas_remakeConstraints與mas_updateConstraints比較相似瘾境,都是更新constraint歧杏。不過,mas_remakeConstraints是刪除之前constraint迷守,然后再添加新的constraint(適用于移動(dòng)動(dòng)畫)犬绒;而mas_updateConstraints只是更新constraint的值。

- (void)changeButtonPosition {? ? [self.button mas_remakeConstraints:^(MASConstraintMaker *make) {? ? ? ? make.size.equalTo(self.buttonSize);if(topLeft) {? ? ? ? ? ? make.top.and.left.offset(10);? ? ? ? }else{? ? ? ? ? ? make.bottom.and.right.offset(-10);? ? ? ? }? ? }];}

想了解以上三個(gè)代碼片段的更多細(xì)節(jié)兑凿,可以下載Masonry iOS Examples工程查閱凯力。

Classy

Classy簡(jiǎn)介和特性

Classy是一個(gè)能與UIKit無縫結(jié)合stylesheet(樣式)系統(tǒng)茵瘾。它借鑒CSS的思想,但引入新的語法和命名規(guī)則咐鹤。

靈活內(nèi)嵌的語法

{}:;這些語法符號(hào)是可選的拗秘,你可以選擇適合自己的風(fēng)格來表達(dá)stylesheet。

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

$main-color =#e1e1e1;MYCustomView { background-color: $main-color; title-insets:5,10,5,10; >UIProgressView.tinted {? progress-tint-color: black;? track-tint-color: yellow; }}^UIButton.warning,UIView.warning ^UIButton{ title-color[state:highlighted]:#e3e3e3;}

或者你使用空格來限定stylesheet

$main-color =#e1e1e1MYCustomView? background-color $main-color? title-insets5,10,5,10>UIProgressView.tinted? ? progress-tint-color black? ? track-tint-color yellow^UIButton.warning,UIView.warning ^UIButtontitle-color[state:highlighted]#e3e3e3

默認(rèn)樣式

Classy在應(yīng)用程序Bundle默認(rèn)查找文件名為stylesheet.cas的樣式文件祈惶。如果你采用這個(gè)文件名雕旨,你可以不用做任何東西就能加載樣式文件。

但如果你想指定其他file path(樣式文件名)捧请,你可以創(chuàng)建[CASStyler defaultStyler]

[CASStylerdefaultStyler].filePath = [[NSBundlemainBundle] pathForResource:@"myStyles.cas"ofType:nil];

如果你還想當(dāng)發(fā)生錯(cuò)誤時(shí)奸腺,獲取錯(cuò)誤信息以便于調(diào)試,可以使用-(void)setFilePath:error:

NSError*error =nil;NSStringfilePath = [[NSBundlemainBundle] pathForResource:@"myStyles.cas"ofType:nil];[[CASStylerdefaultStyler] setFilePath:filePath error:&error];

如果你是使用Storyboard/Xib組織UI界面血久,那就需要在main.m的int main(int argc, char * argv[])方法設(shè)置** filePath,這樣可以確保在創(chuàng)建UIWindow之前加載stylesheet帮非。否則(采用手寫UI代碼)氧吐,你在AppDelegate.m的- (BOOL)application:didFinishLaunchingWithOptions:方法設(shè)置filePath**

Live Reload

Live Reload是實(shí)時(shí)顯示編寫UI代碼效果的關(guān)鍵特性,它能夠?qū)崟r(shí)檢查stylesheet文件變化末盔,無需重新編譯筑舅、構(gòu)建和運(yùn)行模擬器,從而極大提高開發(fā)速度陨舱。

為了啟用Live Reload翠拣,你需要指定stylesheet路徑,并且只運(yùn)行在模擬器上游盲。

#if TARGET_IPHONE_SIMULATORNSString*absoluteFilePath =CASAbsoluteFilePath(@"../Styles/stylesheet.cas");? ? [CASStylerdefaultStyler].watchFilePath = absoluteFilePath;#endif

Selectors

Style Selectors是指定哪個(gè)view使用哪種樣式的方式误墓。主要有三種方法來指定目標(biāo)view:

Object Class

View Hierarchy

Style Class

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

/* match views

* where class is UIButton or UIButton subclass

* and styleClass is "large"

* and superview class is UITabBar

*/UITabBar> ^UIButton.large { }

想了解具體如何使用益缎,請(qǐng)查閱官網(wǎng)Selectors章節(jié)

為了避免與Objective-C的message selectors混淆谜慌,術(shù)語style selectors表示Classy stylesheets的selectors

Properties

Classy支持所有UIAppearance的屬性和方法,也支持與UIAppearance無關(guān)的很多屬性莺奔。Classy使用與UIKit相同屬性命名欣范,所以你不必考慮如何將style property映射到Objective-C的property

UIPageControl類的屬性如下:

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

style property的名字采用與objective-c一樣的名字

UIPageControl{? pageIndicatorTintColor black? currentPageIndicatorTintColor purple}

style property的命名規(guī)則采用kebab case

UIPageControl{? page-indicator-tint-color black? current-page-indicator-tint-color purple}

想了解具體如何使用令哟,請(qǐng)查閱官網(wǎng)Properties章節(jié)

Keep it DRY(Don't Repeat Yourself)

在編程中一個(gè)很重要的原則就是避免重復(fù)恼琼,這不僅可以大量減少重復(fù)代碼,并且使得代碼更加容易復(fù)用和維護(hù)屏富。Classy提供三種方式避免代碼重復(fù):grouping,nesting晴竞,variables

Grouping

如果有兩個(gè)以上的style selectors共用相同的屬性時(shí)

UISlider.info {? minimum-track-tint-color black? maximum-track-tint-color purple}UISlider.error {? minimum-track-tint-color black? maximum-track-tint-color purple? thumb-tint-color red}

我們可以提取相同的屬性到分組style selector中

UISlider.info,UISlider.error {? minimum-track-tint-color black? maximum-track-tint-color purple}UISlider.error {? thumb-tint-color red}

Nesting

如果兩個(gè)以上style selectors共用相同的view hierarchy時(shí)

UICollectionView{? background-color#a2a2a2}UICollectionView>UICollectionViewCell{? clips-to-boundsNO}UICollectionView>UICollectionViewCellUILabel{? text-color purple}UICollectionView>UICollectionViewCellUILabel.title {? font20}

我們通過nesting方式將view hierarchies表達(dá)成這樣方式

UICollectionView{? background-color#a2a2a2>UICollectionViewCell{? ? clips-to-boundsNOUILabel{? ? ? text-color purple? ? ? ? ? ? &.title {? ? ? ? font20}? ? }? }}

Variables

Classy讓你通過定義variables來將多個(gè)相同的style property值存儲(chǔ)以便共享。Variable命名規(guī)則如下:

必須以大小寫字母或$符號(hào)開頭

可以包含_役听,-或任何字母數(shù)字

// prefix with' $ 'tohelpdistinguish variables$brand-color =#e1e1e1// OR notinsets = 5, 10, 5, 10UIButton {? background-color$brand-color? contentEdgeInsets insets? background-image[state:selected] bg_button insets}

最后官方還提供一個(gè)實(shí)例來解釋具體如何使用:Custom Views Example

ClassyLiveLayout

ClassyLiveLayout通過結(jié)合Classy stylesheets與Masonry一起使用颓鲜,能夠在運(yùn)行的模擬器中微調(diào)Auto Layout約束實(shí)時(shí)顯示效果的工具表窘。

ClassyLiveLayout一個(gè)核心category:UIView+ClassyLayoutProperties,在UIView定義以下屬性:

@property(nonatomic,assign)UIEdgeInsetscas_margin;@property(nonatomic,assign)CGSizecas_size;// shorthand properties for setting only a single constant value@property(nonatomic,assign)CGFloatcas_sizeWidth;@property(nonatomic,assign)CGFloatcas_sizeHeight;@property(nonatomic,assign)CGFloatcas_marginTop;@property(nonatomic,assign)CGFloatcas_marginLeft;@property(nonatomic,assign)CGFloatcas_marginBottom;@property(nonatomic,assign)CGFloatcas_marginRight;

cas_margin和cas_size分別表示UI元素的位置和大小甜滨,而其余的屬性都是對(duì)兩個(gè)屬性進(jìn)一步細(xì)分乐严。我們可以從stylesheets中訪問style properties來定義constraints布局,做到將數(shù)據(jù)與代碼分離衣摩,有利于修改和復(fù)用代碼昂验。

UIView.blue-box{cas_size:80100cas_margin-top:60cas_margin-left:50}UIView.red-box{cas_size-width:120cas_margin-left:20}

我們可以在updateConstraints或updateViewConstrains定義布局時(shí)引用style properties

- (void)updateViewConstraints {? [superupdateViewConstraints];? [_blueBoxView mas_updateConstraints:^(MASConstraintMaker *make) {? ? ? make.width.equalTo(@(_blueBoxView.cas_size.width));? ? ? make.height.equalTo(@(_blueBoxView.cas_size.height));? ? ? make.top.equalTo(@(_blueBoxView.cas_margin.top));? ? ? make.left.equalTo(@(_blueBoxView.cas_margin.left));? }];? [_redBoxView mas_updateConstraints:^(MASConstraintMaker *make) {? ? ? make.width.equalTo(@(_redBoxView.cas_size.width));? ? ? make.height.equalTo(_blueBoxView);? ? ? make.top.equalTo(_blueBoxView);? ? ? make.left.equalTo(_blueBoxView.mas_right).with.offset(_redBoxView.cas_margin.left);? }];}

當(dāng)定義view layouts時(shí),將Auto Layout的constraints都放在stylesheets中實(shí)時(shí)加載(Live reload)艾扮。如果你修改constraints既琴,無需重新編譯、構(gòu)建和運(yùn)行模擬器便能實(shí)時(shí)看到修改后的效果泡嘴。

示例工程

配置工程

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

pod'Masonry','~> 0.6.1'pod'Classy','~> 0.2.4'pod'ClassyLiveLayout','~> 0.6.0'

編寫代碼

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

當(dāng)安裝好Masonry酌予,Classy和ClassyLiveLayout后磺箕,第一次運(yùn)行項(xiàng)目會(huì)出現(xiàn)沒有stylesheet.cas文件錯(cuò)誤:

No stylesheet.cas file error.png

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

Create stylesheet.cas file.png

2. 創(chuàng)建LiveView類抛虫,該類繼承SHPAbstractView松靡。

Create LiveView inherit SHPAbstractView.png

在ViewController創(chuàng)建LiveView對(duì)象,然后被self.view引用建椰。

Setup root view in ViewController.png

當(dāng)編譯運(yùn)行時(shí)雕欺,在SHPAbstractView.h由于找不到UIView出現(xiàn)編譯錯(cuò)誤。

SHPAbstractView Compile error.png

只需引入U(xiǎn)IKit便可以解決棉姐,但運(yùn)行一下應(yīng)用程序屠列,出現(xiàn)一下錯(cuò)誤:

Must override methods.png

主要原因是任何自定義UIView繼承SHPAbstractView都需要override兩個(gè)方法:- (void)addSubviews和- (void)defineLayout,我們可以查看SHPAbstractView的源碼可知:

SHPAbstractView Source Code .png

所以只要在LiveView.m文件覆蓋兩個(gè)方法即可

#pragmamark - Add subviews anddefinelayout- (void)addSubviews{}- (void)defineLayout{}

3. LiveView類設(shè)計(jì)

LiveView主要由包含redBoxView和blueBoxView兩個(gè)屬性谅海,redBoxView表示紅色方塊脸哀,blueBoxView表示藍(lán)色方塊。

#import"SHPAbstractView.h"@interfaceLiveView:SHPAbstractView@property(strong,nonatomic)UIView*redBoxView;@property(strong,nonatomic)UIView*blueBoxView;@end

4. LiveView類實(shí)現(xiàn)

由于SHPAbstractView類如何初始化View已經(jīng)做了處理扭吁,暴露兩個(gè)接口- (void)addSubviews和-(void)defineLayout分別處理構(gòu)建view hierarchy和定義布局撞蜂,子類只要覆蓋SHPAbstractView這兩個(gè)方法就可以創(chuàng)建LiveView了。

但是我們將Auto Layout的constraints都放在stylesheets中實(shí)時(shí)加載(Live reload)侥袜,即放在本工程的stylesheet.cas文件蝌诡,將布局?jǐn)?shù)據(jù)和布局代碼分離。

UIView.redBox {? ? cas_marginTop50cas_marginLeft20cas_size100100}UIView.blueBox {? ? cas_marginTop50cas_marginRight-20cas_size100100}

有了constraints數(shù)據(jù)后枫吧,便可以在代碼布局:

@implementationLiveView#pragma mark - Add subviews and define layout- (void)addSubviews{self.backgroundColor = [UIColorwhiteColor];? ? [selfaddSubview:self.redBoxView];? ? [selfaddSubview:self.blueBoxView];}- (void)defineLayout{? ? [self.redBoxView mas_updateConstraints:^(MASConstraintMaker* make){? ? ? ? make.top.equalTo(@(self.redBoxView.cas_marginTop));? ? ? ? make.left.equalTo(@(self.redBoxView.cas_marginLeft));? ? ? ? make.width.equalTo(@(self.redBoxView.cas_sizeWidth));? ? ? ? make.height.equalTo(@(self.redBoxView.cas_sizeHeight));? ? }];? ? ? ? [self.blueBoxView mas_updateConstraints:^(MASConstraintMaker *make){? ? ? ? make.top.equalTo(@(self.blueBoxView.cas_marginTop));? ? ? ? make.right.equalTo(@(self.blueBoxView.cas_marginRight));? ? ? ? make.width.equalTo(@(self.blueBoxView.cas_sizeWidth));? ? ? ? make.height.equalTo(@(self.blueBoxView.cas_sizeHeight));? ? }];}#pragma mark - Lazy initialization- (UIView*)redBoxView{if(!_redBoxView) {? ? ? ? _redBoxView = [UIViewnew];? ? ? ? _redBoxView.cas_styleClass =@"redBox";? ? ? ? _redBoxView.backgroundColor = [UIColorredColor];? ? }return_redBoxView;}- (UIView*)blueBoxView{if(!_blueBoxView) {? ? ? ? _blueBoxView = [UIViewnew];? ? ? ? _blueBoxView.cas_styleClass =@"blueBox";? ? ? ? _blueBoxView.backgroundColor = [UIColorblueColor];? ? }return_blueBoxView;}

5. 模擬器支持Live Reload

為了啟用Live Reload浦旱,你需要指定stylesheet路徑,并且只運(yùn)行在模擬器上九杂。

Support Live Reload.png

此時(shí)效果:

Live Change.gif

6. 分離樣式文件

由于有網(wǎng)友提出這樣一個(gè)問題:如果所有view的樣式都放在同一個(gè)stylesheet.cas文件颁湖,會(huì)讓stylesheet.cas文件繁雜宣蠕,并且當(dāng)多個(gè)人協(xié)同開發(fā)時(shí),不易于合并代碼甥捺,所以有必要將樣式文件分離到多個(gè)文件中抢蚀。

創(chuàng)建variable.cas文件,并將redBox對(duì)應(yīng)UIView的樣式放在variable.cas文件中镰禾。

variable.cas file.png

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

stylesheet.cas file.png

最后效果

Live Change 1.gif

Live Change 2.gif

示例代碼存放地址:LiveAutoLayout

總結(jié)

之前手寫UI代碼每次更改一般都要重新編譯皿曲、構(gòu)建和運(yùn)行模擬器才能看到效果,但結(jié)合使用Masonry吴侦,Classy和ClassLiveLayout之后屋休,告別這個(gè)費(fèi)時(shí)過程,極大地提高開發(fā)速度备韧;不僅如此劫樟,我們將Auto Layout的constraints都放在stylesheets中實(shí)時(shí)加載(Live reload),將布局?jǐn)?shù)據(jù)和布局代碼分離织堂,使得代碼更加復(fù)用和維護(hù)毅哗。Classy還提供三種避免重復(fù)方法:Grouping, Nestting和Variable,盡可能復(fù)用樣式數(shù)據(jù)捧挺。

這是本人第一次編寫技術(shù)博客,可能有很多錯(cuò)誤和漏洞尿瞭,希望大家多多指點(diǎn)闽烙,也希望這篇文章能夠幫助到大家声搁。

擴(kuò)展閱讀

Storyboard/XIB與手寫代碼的選擇

代碼手寫UI黑竞,xib和StoryBoard間的博弈,以及Interface Builder的一些小技巧

iOS 開發(fā)中的爭(zhēng)議(二)

Storyboard可視化開發(fā)

Adaptive Layout Tutorial: Getting Started

WWDC 2014 Session筆記 - 可視化開發(fā)谁榜,IB 的新時(shí)代

AutoLayout與Masonry

iOS 開發(fā)實(shí)踐之 Auto Layout

深入理解Auto Layout 第一彈

Masonry介紹與使用實(shí)踐

Auto Layout WWDC 視頻集合

WWDC 2012: Introduction to Auto Layout for iOS and OS X

WWDC 2012: Best Practices for Mastering Auto Layout

WWDC 2012: Auto Layout by Example

WWDC 2013: Taking Control of Auto Layout in Xcode 5

作者:Sam_Lau

鏈接:http://www.reibang.com/p/2ed5f7444900

來源:簡(jiǎn)書

著作權(quán)歸作者所有幅聘。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處窃植。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末帝蒿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子巷怜,更是在濱河造成了極大的恐慌葛超,老刑警劉巖暴氏,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绣张,居然都是意外死亡答渔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門胖替,熙熙樓的掌柜王于貴愁眉苦臉地迎上來研儒,“玉大人,你說我怎么就攤上這事独令《硕洌” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵燃箭,是天一觀的道長(zhǎng)冲呢。 經(jīng)常有香客問我,道長(zhǎng)招狸,這世上最難降的妖魔是什么敬拓? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮裙戏,結(jié)果婚禮上乘凸,老公的妹妹穿的比我還像新娘。我一直安慰自己累榜,他們只是感情好营勤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著壹罚,像睡著了一般葛作。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猖凛,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天赂蠢,我揣著相機(jī)與錄音,去河邊找鬼辨泳。 笑死虱岂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的菠红。 我是一名探鬼主播量瓜,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼途乃!你這毒婦竟也來了绍傲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烫饼,沒想到半個(gè)月后猎塞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杠纵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年荠耽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片比藻。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铝量,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出银亲,到底是詐尸還是另有隱情慢叨,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布务蝠,位于F島的核電站拍谐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏馏段。R本人自食惡果不足惜轩拨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望院喜。 院中可真熱鬧亡蓉,春花似錦、人聲如沸喷舀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽元咙。三九已至,卻和暖如春巫员,著一層夾襖步出監(jiān)牢的瞬間庶香,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來泰國打工简识, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赶掖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓七扰,卻偏偏與公主長(zhǎng)得像奢赂,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子颈走,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 編寫iOS應(yīng)用UI的方式大概有兩種膳灶,一種是Storyboard/Xib,另一種是手寫代碼。采用Storyboard...
    Sam_Lau閱讀 60,694評(píng)論 69 400
  • (一)Masonry介紹 Masonry是一個(gè)輕量級(jí)的布局框架 擁有自己的描述語法 采用更優(yōu)雅的鏈?zhǔn)秸Z法封裝自動(dòng)布...
    木易林1閱讀 2,334評(píng)論 0 3
  • Masonry是一個(gè)輕量級(jí)的布局框架轧钓,擁有自己的描述語法序厉,采用更優(yōu)雅的鏈?zhǔn)秸Z法封裝自動(dòng)布局,簡(jiǎn)潔明了并具有高可讀性...
    3dcc6cf93bb5閱讀 1,765評(píng)論 0 1
  • 一毕箍、前言 關(guān)于蘋果的布局一直是我比較糾結(jié)的問題弛房,是寫代碼來控制布局,還是使用storyboard來控制布局呢而柑?以前...
    iplaycodex閱讀 2,446評(píng)論 0 1
  • iOS_autoLayout_Masonry 概述 Masonry是一個(gè)輕量級(jí)的布局框架與更好的包裝AutoLay...
    指尖的跳動(dòng)閱讀 1,162評(píng)論 1 4