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

今天试了下实时显示iOS代码编写UI的效果,记录下方便下次查看。本文是参考实时显示iOS编写UI代码效果大部分和原文相同,如果作者认为我侵犯了他的创作权请与我联系,我马上进行修改。谢谢。(会持续更新并添加图片)

1. 添加第三方支持库

因为想要实时显示iOS代码编写UI的效果需要引用第三方库,当然也要用到依赖库管理工具CocoaPods
在Podfile配置如下:

platform :ios, '6.0'
pod 'Masonry', '~> 0.6.1'
pod 'Classy', '~> 0.2.4'
pod 'ClassyLiveLayout', '~> 0.6.0'

#2. 编写代码

  1. 添加stylesheet.cas文件到工程
  2. 创建LiveView类,该类继承自SHPAbstractView
  3. ViewController创建LiveView对象,然后被self.view引用。
  4. 当编译运行时,在SHPAbstractView由于找不到UIView会出现编译错误。
    需要引入UIKit便可以解决,但运行一下会出现错误:

    Undefined symbols for architecture x86_64:
    "_OBJC_CLASS_$_CASStyler", referenced from:
         objc-class-ref in AppDelegate.o
    "_OBJC_CLASS_$_SHPAbstractView", referenced from:
         _OBJC_CLASS_$_LiveView in LiveView.o
    "_OBJC_METACLASS_$_SHPAbstractView", referenced from:
         _OBJC_METACLASS_$_LiveView in LiveView.o
    "__CASAbsoluteFilePath", referenced from:
         -[AppDelegate application:didFinishLaunchingWithOptions:] in AppDelegate.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    

这是因为对应的libPods-Masonry.alibPods-Classy.alibPods-ClassyLiveLayout.a没有在Link Binary With Libraries中加入。(不知道我的为什么是这样子,一般都是有个libPods.a就够了的,原因可能和我使用的是cordova的原因吧).加入以后就可以了。

  1. 但是运行以后会出现下面的崩溃信息

    2015-05-10 22:52:50.204 WebTest[5368:62482] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Must override'
    

这个是因为任何继承自SHPAbstractView的UIView都需要override两个方法:- (void)addSubviews- (void)defineLayout,通过查看SHPAbstractView.h的源码就知道:

#import <Foundation/Foundation.h>


@interface SHPAbstractView : UIView

// You must override these methods in subclasses

/// Override this method and add all subviews in it
- (void)addSubviews;

/// Override this method and use the mas_updateConstraints... methods to add constraints
/// It's important to use the 'update' methods as this may be called multiple times.
- (void)defineLayout;

所以在LiveView.m文件中覆盖2个方法就好

#pragma mark - override 
- (void)addSubviews
{
}

- (void)defineLayout
{
}

3.LiveView中的属性

#import "SHPAbstractView.h"

@interface LiveView : SHPAbstractView

@property (strong, nonatomic) UIView *redBoxView;
@property (strong, nonatomic) UIView *blueBoxView;

@end

4.LiveView的实现

#import "LiveView.h"
#import <Masonry/Masonry.h>
#import <ClassyLiveLayout/ClassyLiveLayout.h>
#import <Classy/Classy.h>
@implementation LiveView

- (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.right.equalTo(@(self.redBoxView.cas_marginRight));
        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;
}

我们需要将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
}

5. 启动模拟器支持Live Reload

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
#if TARGET_IPHONE_SIMULATOR
    NSString *absoluteFilePath = CASAbsoluteFilePath(@"stylesheet.cas");
    [CASStyler defaultStyler].watchFilePath = absoluteFilePath;
#endif

这时候就已经可以动态显示(不过在你修改stylesheet.cas以后,需要command + s保存才能正确动态的显示效果图。)

6. 更加合理的cas文件结构

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

    UIView.redBox {
        cas_marginTop 50
        cas_marginLeft 20
        cas_marginRight -200
    
        cas_size 100 100
    }
    
  2. 在stylesheet.cas样式文件使用@import指令引用variable.cas文件

    @import "variable.cas";
    
    UIView.blueBox {
    cas_marginTop 50
    cas_marginRight -20
    
    cas_size 100 100
    }
    
Zerlz wechat
扫码关注一个很懒的程序员!
Winter is coming, give me a penny!