編寫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的一些小技巧
Storyboard可視化開發(fā)
Adaptive Layout Tutorial: Getting Started
WWDC 2014 Session筆記 - 可視化開發(fā)谁榜,IB 的新時(shí)代
AutoLayout與Masonry
iOS 開發(fā)實(shí)踐之 Auto Layout
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)注明出處窃植。