实时显示iOS编写UI代码效果:有效提高UI编写速度

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

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

2

3

4

5

6

7

+ (id)constraintWithItem:(id)view1

               attribute:(NSLayoutAttribute)attribute1

               relatedBy:(NSLayoutRelation)relation

                  toItem:(id)view2

               attribute:(NSLayoutAttribute)attribute2

              multiplier:(CGFloat)multiplier

                constant:(CGFloat)constant;

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

typedef enum: NSInteger {

   NSLayoutAttributeLeft = 1,

   NSLayoutAttributeRight,

   NSLayoutAttributeTop,

   NSLayoutAttributeBottom,

   NSLayoutAttributeLeading,

   NSLayoutAttributeTrailing,

   NSLayoutAttributeWidth,

   NSLayoutAttributeHeight,

   NSLayoutAttributeCenterX,

   NSLayoutAttributeCenterY,

   NSLayoutAttributeBaseline,

   NSLayoutAttributeNotAnAttribute = 0

} NSLayoutAttribute;

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


1

view1.attribute1 = view2.attribute2 * multiplier + constant

第二种方式是:


1

2

3

4

+ (NSArray *)constraintsWithVisualFormat:(NSString *)format 

                                 options:(NSLayoutFormatOptions)opts 

                                 metrics:(NSDictionary *)metrics 

                                   views:(NSDictionary *)views;

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

Auto Layout存在问题

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

UIView *superview = self;

UIView *view1 = [[UIView alloc] init];

view1.translatesAutoresizingMaskIntoConstraints = NO;

view1.backgroundColor = [UIColor greenColor];

[superview addSubview:view1];

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[superview addConstraints:@[

    //view1 constraints

    [NSLayoutConstraint constraintWithItem:view1

                                 attribute:NSLayoutAttributeTop

                                 relatedBy:NSLayoutRelationEqual

                                    toItem:superview

                                 attribute:NSLayoutAttributeTop

                                multiplier:1.0

                                  constant:padding.top],

    [NSLayoutConstraint constraintWithItem:view1

                                 attribute:NSLayoutAttributeLeft

                                 relatedBy:NSLayoutRelationEqual

                                    toItem:superview

                                 attribute:NSLayoutAttributeLeft

                                multiplier:1.0

                                  constant:padding.left],

    [NSLayoutConstraint constraintWithItem:view1

                                 attribute:NSLayoutAttributeBottom

                                 relatedBy:NSLayoutRelationEqual

                                    toItem:superview

                                 attribute:NSLayoutAttributeBottom

                                multiplier:1.0

                                  constant:-padding.bottom],

    [NSLayoutConstraint constraintWithItem:view1

                                 attribute:NSLayoutAttributeRight

                                 relatedBy:NSLayoutRelationEqual

                                    toItem:superview

                                 attribute:NSLayoutAttributeRight

                                multiplier:1

                                  constant:-padding.right],

 ]];

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

Masonry

为什么使用Masonry

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

使用Masonry的MASConstraintMaker来表达相同constraint


1

2

3

4

5

6

7

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {

    make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an 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);

}];

甚至可以更短


1

2

3

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {

    make.edges.equalTo(superview).with.insets(padding);

}];

如何使用

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

1. mas_makeConstraints

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


1

2

3

4

5

6

7

8

9

10

11

// 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

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

// 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

    [super updateConstraints];

}

3. mas_remakeConstraints

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


1

2

3

4

5

6

7

8

9

10

- (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);

        }

    }];

}

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

Classy

Classy简介和特性

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

灵活内嵌的语法

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

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


1

2

3

4

5

6

7

8

9

10

11

12

$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


1

2

3

4

5

6

7

8

9

$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

默认样式

Classy在应用程序Bundle默认查找文件名为stylesheet.cas的样式文件。如果你采用这个文件名,你可以不用做任何东西就能加载样式文件。

但如果你想指定其他file path(样式文件名),你可以创建[CASStyler defaultStyler]


1

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

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


1

2

3

NSError *error = nil;

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

[[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

2

3

4

#if TARGET_IPHONE_SIMULATOR

    NSString *absoluteFilePath = CASAbsoluteFilePath(@"../Styles/stylesheet.cas");

    [CASStyler defaultStyler].watchFilePath = absoluteFilePath;

#endif

Selectors

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

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

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


1

2

3

4

5

6

/* match views

 * where class is UIButton or UIButton subclass

 * and styleClass is "large"

 * and superview class is UITabBar

 */

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

2

@property (nonatomic,retain) UIColor *pageIndicatorTintColor;

@property (nonatomic,retain) UIColor *currentPageIndicatorTintColor;

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


1

2

3

4

UIPageControl {

  pageIndicatorTintColor black

  currentPageIndicatorTintColor purple

}

style property的命名规则采用kebab case

UIPageControl {

page-indicator-tint-color black

current-page-indicator-tint-color purple

}

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

Keep it DRY(Don‘t Repeat Yourself)

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

Grouping

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


1

2

3

4

5

6

7

8

9

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中


1

2

3

4

5

6

7

UISlider.info, UISlider.error {

  minimum-track-tint-color black

  maximum-track-tint-color purple

}

UISlider.error {

  thumb-tint-color red

}

Nesting

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


1

2

3

4

5

6

7

8

9

10

11

12

UICollectionView {

  background-color #a2a2a2

}

UICollectionView > UICollectionViewCell {

  clips-to-bounds NO

}

UICollectionView > UICollectionViewCell UILabel {

  text-color purple

}

UICollectionView > UICollectionViewCell UILabel.title {

  font 20

}

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


1

2

3

4

5

6

7

8

9

10

11

12

UICollectionView {

  background-color #a2a2a2

  > UICollectionViewCell {

    clips-to-bounds NO

    UILabel {

      text-color purple

      &.title {

        font 20

      }

    }

  }

}

Variables

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

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

1

2

3

4

5

6

7

8

9

// prefix with ‘ $ ‘ to help distinguish variables

$brand-color = #e1e1e1

// OR not

insets = 5, 10, 5, 10

UIButton {

  background-color $brand-color

  contentEdgeInsets insets

  background-image[state:selected] bg_button insets

}

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

ClassyLiveLayout

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

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


1

2

3

4

5

6

7

8

9

@property(nonatomic, assign) UIEdgeInsets cas_margin;

@property(nonatomic, assign) CGSize cas_size;

// shorthand properties for setting only a single constant value

@property(nonatomic, assign) CGFloat cas_sizeWidth;

@property(nonatomic, assign) CGFloat cas_sizeHeight;

@property(nonatomic, assign) CGFloat cas_marginTop;

@property(nonatomic, assign) CGFloat cas_marginLeft;

@property(nonatomic, assign) CGFloat cas_marginBottom;

@property(nonatomic, assign) CGFloat cas_marginRight;

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


1

2

3

4

5

6

7

8

9

UIView.blue-box {

    cas_size: 80 100

    cas_margin-top: 60

    cas_margin-left: 50

}

UIView.red-box {

    cas_size-width: 120

    cas_margin-left: 20

}

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

- (void)updateViewConstraints {

  [super updateViewConstraints];

  [_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);

  }];

}

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

示例工程

配置工程

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


1

2

3

pod ‘Masonry‘‘~> 0.6.1‘

pod ‘Classy‘‘~> 0.2.4‘

pod ‘ClassyLiveLayout‘‘~> 0.6.0‘

编写代码

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

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

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

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

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

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

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

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

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


1

2

3

4

5

6

7

#pragma mark - Add subviews and define layout

- (void)addSubviews

{

}

- (void)defineLayout

{

}

3. LiveView类设计

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


1

2

3

4

5

#import "SHPAbstractView.h"

@interface LiveView : SHPAbstractView

@property (strong, nonatomic) UIView *redBoxView;

@property (strong, nonatomic) UIView *blueBoxView;

@end

4. LiveView类实现

由于SHPAbstractView类如何初始化View已经做了处理,暴露两个接口- (void)addSubviews和-(void)defineLayout分别处理构建view hierarchy和定义布局,子类只要覆盖SHPAbstractView这两个方法就可以创建LiveView了。

但是我们将Auto Layout的constraints都放在stylesheets中实时加载(Live reload),即放在本工程的stylesheet.cas文件,将布局数据和布局代码分离。


1

2

3

4

5

6

7

8

9

10

UIView.redBox {

    cas_marginTop 50

    cas_marginLeft 20

    cas_size 100 100

}

UIView.blueBox {

    cas_marginTop 50

    cas_marginRight -20

    cas_size 100 100

}

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

@implementation LiveView

#pragma mark - Add subviews and define layout

- (void)addSubviews

{

    self.backgroundColor = [UIColor whiteColor];

    [self addSubview:self.redBoxView];

    [self addSubview: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 = [UIView new];

        _redBoxView.cas_styleClass = @"redBox";

        _redBoxView.backgroundColor = [UIColor redColor];

    }

    return _redBoxView;

}

- (UIView*)blueBoxView

{

    if (!_blueBoxView) {

        _blueBoxView = [UIView new];

        _blueBoxView.cas_styleClass = @"blueBox";

        _blueBoxView.backgroundColor = [UIColor blueColor];

    }

    return _blueBoxView;

}

5. 模拟器支持Live Reload

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

最后效果

示例代码存放地址:LiveAutoLayout

总结

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

这是本人第一次编写技术博客,可能有很多错误和漏洞,希望大家多多指点,也希望这篇文章能够帮助到大家。

扩展阅读

时间: 2024-10-13 12:34:26

实时显示iOS编写UI代码效果:有效提高UI编写速度的相关文章

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

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

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

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

JavaScript实现页面实时显示时间

今天尝试了一下JavaScript实现页面实时显示时间 运用了 setInterval() 函数 setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式 setInterval("getTime()",1000); 以1000毫秒间隔调用函数有一个问题就是刚打开页面时的1s会不显示 为此我们可以在之前先调用一遍函数 getTime(); 这样无论何时都能实时显示时间啦 .html代码如下 <!DOCTYPE html> <html lang

iOS之UISearchBar实时显示结果

iOS之UISearchBar实时显示结果 UISearchBar 经常是配合UITableView 一起使用的,一般都将UITableView的tableHeaderView属性设置为UISearchBar.使用UISearchBar需要实现UISearchBarDelegate 中的三个方法. //取消按钮被点击的时候 -(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar: //搜索按钮被点击的时候 -(void)searc

关于多线程的一个例子(UI实时显示)

在开发Window应用程序的时候,经常需要在界面上显示出已经执行到什么步骤了,拿一个简单例子来说,创建一个Winform程序,在窗体上访一个Button和一个Label,点击Button时做100次循环,在Label上实时显示当前循环的次数.一种简单的做法就是使用Application.DoEvents,代码如下: private void btnTest_Click(object sender, EventArgs e) { for (int i = 0; i < 100; i++) { Th

编写可读性代码的艺术

在做IT的公司里,尤其是软件开发部门,一般不会要求工程师衣着正式.在我工作过的一些环境相对宽松的公司里,很多程序员的衣着连得体都算不上(搞笑的T恤.短裤.拖鞋或者干脆不穿鞋).我想,我本人也在这个行列里面.虽然我现在改行做软件开发方面的咨询工作,但还是改不了这副德性.衣着体面的其中一个积极方面是它体现了对周围人的尊重,以及对所从事工作的尊重.比如,那些研究市场的人要表现出对客户的尊重.而大多数程序员基本上每天主要的工作就是和其他程序员打交道.那么这说明程序员之间就不用互相尊重吗?而且也不用尊重自

IOS基础UI之(三)手写UI和storyboard方式实现图片移动和缩放

手写UI是最早进行UI界面布局的方法,优点是灵活自由,缺点是使代码看起来比较长.平时学习的时候可以多尝试手写ui,这样会更深入熟悉控件.storyboard开发效率相对比较高.实际开发中看情况而定!! 下面用这两种方式分别实现图片移动和缩放. 功能描述: 1. 界面布局 2.点击相应的按钮,对显示的图片移动.缩放. 效果如下:    掌握点: 一:熟悉代码的描述UIButton属性 1.UIButton状态 UIControlStateNormal          // 正常状态 UICont

AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码

AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码 添加Watch应用对象时新增内容介绍 Watch应用对象添加到创建的项目中后,会包含两个部分:Watch App 和 WatchKit Extension,如图2.18所示.其中,Watch App部分位于用户的iWatch上,它目前为止只允许包含Storyboard文件和Resources文件.在我们的项目里,这一部分不包括任何代码.WatchKit Extension部分位于用户的iPhone安装的对应App上,这

react-native-pg-style使用方法(以最简单的方式编写样式代码)

react-native-pg-style 以最简单的方式编写样式代码,抛弃react-native标准的样式创建方式. 看大家写的源码中都是按照react-native标准的样式创建方式来写样式代码的,样式代码就占了大概四分之一,甚至三分之一的代码,然而我却喜欢把样式写在一行当中.而不用const styles=StyleSheet.create({样式属性...})来写,我觉得这样在改动样式时便不用在跑到StyleSheet.create中修改,而且代码量会少很多,于是就有了这个插件. 下面