美文网首页不明觉厉iOSiOS开发技术iOS
实时显示iOS编写UI代码效果

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

作者: Sam_Lau | 来源:发表于2015-04-23 15:53 被阅读53745次

    编写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对象主要有两种方式,第一种是

    + (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主要由表示位置(上/下/左/右)和大小(宽/高)的以下几个值:

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

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

    view1.attribute1 = view2.attribute2 * multiplier + constant
    

    第二种方式是:

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

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

    Auto Layout存在问题

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

    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

    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);
    }];
    

    甚至可以更短

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

    如何使用

    使用Masonry创建constraint来定义布局的方式有三种:mas_makeConstraintsmas_updateConstraintsmas_remakeConstraints

    1. mas_makeConstraints

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

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

    // 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_remakeConstraintsmas_updateConstraints比较相似,都是更新constraint。不过,mas_remakeConstraints是删除之前constraint,然后再添加新的constraint(适用于移动动画);而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);
            }
        }];
    }
    

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

    Classy

    Classy简介和特性

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

    灵活内嵌的语法

    { } : ; 这些语法符号是可选的,你可以选择适合自己的风格来表达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 = #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]

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

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

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

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

    Live Reload

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

    #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

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

    /* 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类的属性如下:

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

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

    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, nestingvariables

    Grouping

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

    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

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

    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表达成这样方式

    UICollectionView {
      background-color #a2a2a2
      
      > UICollectionViewCell {
        clips-to-bounds NO
        
        UILabel {
          text-color purple
          
          &.title {
            font 20
          }
        }
      }
    }
    
    Variables

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

    • 必须以大小写字母$符号开头
    • 可以包含_-或任何字母数字
    // 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定义以下属性:

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

    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
    }
    

    我们可以在updateConstraintsupdateViewConstrains定义布局时引用style properties

    - (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配置如下:

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

    编写代码

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

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


    No stylesheet.cas file error.png

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


    Create stylesheet.cas file.png
    2. 创建LiveView类,该类继承SHPAbstractView
    Create LiveView inherit SHPAbstractView.png
    ViewController创建LiveView对象,然后被self.view引用。 Setup root view in ViewController.png
    当编译运行时,在SHPAbstractView.h由于找不到UIView出现编译错误。
    SHPAbstractView Compile error.png
    只需引入UIKit便可以解决,但运行一下应用程序,出现一下错误:
    Must override methods.png
    主要原因是任何自定义UIView继承SHPAbstractView都需要override两个方法:- (void)addSubviews- (void)defineLayout,我们可以查看SHPAbstractView的源码可知: SHPAbstractView Source Code .png
    所以只要在LiveView.m文件覆盖两个方法即可
    #pragma mark - Add subviews and define layout
    - (void)addSubviews
    {
    }
    
    - (void)defineLayout
    {
    }
    
    3. LiveView类设计

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

    #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文件,将布局数据和布局代码分离。

    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数据后,便可以在代码布局:

    @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路径,并且只运行在模拟器上。

    Support Live Reload.png

    此时效果:

    Live Change.gif
    6. 分离样式文件

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

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

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

    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,尽可能复用样式数据。
    这是本人第一次编写技术博客,可能有很多错误和漏洞,希望大家多多指点,也希望这篇文章能够帮助到大家。

    扩展阅读

    相关文章

      网友评论

      • coooliang:UIView.redBox 中使用cas_marginRight没有反应为什么?只能用left??
      • 某非著名程序员:18年了,看似强大,这个有人用吗?
      • 星期六下午火锅:您好 classy 有没有对于swift的项目 实用snpkit 布局的呢
      • 谢谢生活:楼主很有爱,感谢楼主分享好东西……
      • 秒赞不是偶然:cas 文件里面能获取到屏幕的高度 和宽度吗
      • Xezun:这玩意的效率如何?
        Xezun:@mlibai 主要是性能
        Sam_Lau:@mlibai 一般般
      • 36bb35d9d1d7:https://github.com/johnno1962/injectionforxcode
        这个插件可以实时更新修改结果
      • 小凡凡520:这么强大的Masonry 竟然没有用过
      • 低吟浅唱1990:下载了demo 但是没有博客上面的效果
        不知哪里出错了
      • e2efcfc2a55a:写的很棒!
      • LeoAu:Classy怎样控制字体粗细 font bold
      • 飞行的孤独员FG:你好,请问代码引用的黄色背景是怎么弄的啊 :joy:
        Jisen:@飞行的孤独员FG markdown编辑
      • Eddie_Zys:受用,赞一个强大的楼主。
      • ZsIsMe:受到您的文章的启发,我发现可以使用IB_DESIGNABLE和Masonry结合的方法,在xib上实时显示Masonry布局代码,我也在简书上分享了,不过水平有限,望指教一下。 :smile:
        http://www.jianshu.com/p/e4accdbfd841
        Sam_Lau:@ZsIsMe 👍🏻👍🏻👍🏻
      • LeoAu:我自己项目上试了一遍,虽然是分离了样式代码,方便维护,但同样文件也是增加了不少,增加了一个对应的LiveView.h & LiveView.m文件,然后在controller里再调用

        > 我认为addSubviews和defineLayout可以写在controller里面,这样就不用维护太多文件,我尝试过在LiveView里面添加delegate,让addSubviews里面去执行这个delegate在controller里实现delegate的方法,可惜失败了,正在研究其原因。当然如果不需要ClassyLiveLayout的话,LiveView大可不必生成
        Sam_Lau:@LeoAu 哈哈,👍🏻👍🏻👍🏻
        LeoAu:@Sam_Lau 确实如您所言,Controller不应该承担画UI的职责,我现在是代码UI+xib混合,一些复杂的界面用代码来维护更加方便和清晰,一些简单固定的界面则直接使用xib(拖几个icon也写一堆代码)。所以也想和博主多交流这方面的经验 :grin:
        Sam_Lau:@LeoAu controller不应该承担画UI的职责,应该交给单独一个view做,当UI复杂时,controller会变得臃肿且不易维护。而且,当view中有些组件可以复用时,更加容易分离出来,而不需要改动controller的代码
      • Sam_Lau:@FAB 对的,但是你在reveal改完之后,还需要在代码还
      • f3f504fa1629:reveal embedded in也能实时改啊
      • 5a419db84a85:照着做,没有实现效果呀?!!!
        5a419db84a85:@5a419db84a85 可以了,尴尬……
      • Sam_Lau:@是我始终拒绝成长吗 应该能,不过没试过,你可以尝试一下
      • 是我始终拒绝成长吗:能不能修改颜色呢
      • DavidLam:既然都用到CSS了还要再结合 auto layout 感觉好蛋疼。
        如果UX的图标注得比较好,感觉好像就没什么必要了。
      • 0edc44a214a9:确实挺不错的
      • Sam_Lau:@周大同 你加我qq吧,784854572
      • datongzhou:@Sam_Lau 😄,不好意思,我还是不会,我的做法是创建一个一般文件,改后缀,那么问题来了,文件的后缀能改,结构不能改啊,还有xcode不能编写他啊,唉,小白,望大神指点
      • 渡云雨:如果不使用Pods 怎么办?
      • xclidongbo: @Sam_Lau 2个,项目着急的话,领导也会加入。
      • Sam_Lau:@xclidongbo 你们公司多少人做一个项目?
      • Sam_Lau:@xclidongbo 每个人的观点和做事方式都可能不同,最重要的是选择最适合自己,同时能提高开发效率就行,没必要强迫,😁😁😁
      • xclidongbo: @Sam_Lau 恩,是的。我不知道你们怎么做项目的。我们公司要求快。恨不能一个项目两到三周搞定。很难想像,一个没有代码补全的东西用到项目里,会给其它同事造成多大麻烦。 我说的可能不中听。另外我的观点也不一定正确。不过非常感谢,你能给大家介绍这么优秀的方式来实时展现UI.
        36bb35d9d1d7:@xclidongbo 可以参考这个代码补全插件https://github.com/poboke/TweakAutocomplete
        xclidongbo:@iOSPro 额,有插件编写的相关教程没?
        余不悟:@xclidongbo 我觉得像代码补全的话,既然你们用得多的话,为什么不写一个代码补全插件.
      • Sam_Lau:@xclidongbo 你是指因为没有代码补全而不成熟吗?
      • xclidongbo: @Sam_Lau 谢谢回复。
      • xclidongbo: @Sam_Lau 看来这种方式在项目开发中还是不成熟。
      • xclidongbo: @Sam_Lau 看来这种方式在项目开发中还是不成熟。
      • Sam_Lau:@xclidongbo 暂时没有暂时没有
      • xclidongbo:我很想知道,stylesheet.cas文件的代码补全和高亮怎么做?
      • Sam_Lau:@MeiganFang 不过,我还是建议在简书讨论,因为这样的话,大家都可以参与讨论
      • Sam_Lau:@MeiganFang 我很少上qq,你在我的主页加我微信吧
      • Sam_Lau:@周大同 跟创建普通文件差不多啊
      • datongzhou:版主,stylesheet.cas这个文件怎么创建啊 ?
        swif的嘛?
      • Sam_Lau:@aaa13413345005 添加什么?
      • 7c31fa924ef4:话说怎么在现有的workspace里面添加这些啊······
      • Sam_Lau:@wingsrao 互相学习吧 :stuck_out_tongue_winking_eye:
      • wingsrao:写得真的不错,向你学习!
      • a0aff3927ae1:感谢分享
      • MeiganFang:博主,这样做,耦合度是否会增加?加个qq 349438233 交流下。 另外刚发现简书登录bug,点登录跳转到简书首页 :sweat:
      • 06067cf1c942:@Sam_Lau 已看到新工程实现方式,谢谢 :smile:
      • 4c93ece99504:web css live load的思路那,值得学习下。
      • dd8a1077569c:masonry 引入我的工程以后 发现 有些 手动 布局代码 报错了 感觉和masattribe冲突了 这种情况遇见过吗
      • Sam_Lau:@雷子恒 博客以及LiveAutoLayout已经更新工程,希望能帮助到你
      • Sam_Lau:@雷子恒 我可以在LiveAutoLayout更新工程,然后你可以参考如何编写!
      • Sam_Lau:@雷子恒 其实你可以创建另一个样式文件,然后在stylesheet.cas引用它,这样就可以分离多个view的样式,同时也可以多人协作开发。
      • 06067cf1c942:一个项目只允许有一个stylesheet.cas吧?那我所有界面的布局设置都写在这个文件里,那这个文件内容会很大啊,后期也不好查找具体哪个控件,文件大了解析速度上也要消费更长时间。如果可以一个界面对应一个cas文件就好了
      • 998eddf8739d:感谢分享
      • CarryIT:给力啊!开启学霸模式!
      • 嘉言火:不错
      • Sam_Lau:@HTC 有什么想法随时欢迎讨论
      • iHTCboy:内容巨大,慢慢吞,谢谢分享!
      • Sam_Lau:有空可以学习一下
      • Sam_Lau:@SuperY 那你是使用原生的NSLayoutConstraint吗?还是选用其他Auto Layout库
      • 6093b85fc556:Masonry 停止维护了 :flushed:
        4ef7e44e7a90:@SuperY 是的.但是原作者又搞了一个https://github.com/SnapKit/SnapKit
      • Huangyuanming:好给力,好好学习

      本文标题:实时显示iOS编写UI代码效果

      本文链接:https://www.haomeiwen.com/subject/lxaufttx.html