Python根据Json生成Objective-c代码

代码地址:https://github.com/LiPengYue/BuildiOSCode.git

目标:

1、 解析UI稿(HTML文件),根据HTML生成完整的Objective-c代码(未完成)

  • 完成了xcode XIB 解析成json,json转Objective-c代码

2、 根据json生成ViewModel、model、View文件,(完成)

3、 根据json自动给模板添加 子视图、视图布局、视图属性赋值的代码(完成)

Json 数据源获取:

一、 UI稿转json(未完成)

终极目标是把蓝湖HTML文件转成一个个可解析的json,然后转成Objective-c代码,但是前端代码不是很熟悉,所以先用xcode的xib进行了json转化

二、 Xcode XIB 转json

XIB 可视化编辑属性

每个子UI视图,生成代码都需要有几个要素:

1、视图样式相关: border、borderColor,backgroundColor,text,image等

2、 网络接口相关:image, text, backgroundColor等

为了在XIB中展示这些接口,方便为json生成提供数据,我在OC demo中添加了几个分类(添加IBInspectable标识,表示可以在xib中展示)

// View
@interface UIView (PYBaseBuildCodeXIB)
@property (nonatomic, assign) IBInspectable   CGFloat  cornerRadius;//圆角
@property (nonatomic, strong) IBInspectable   UIColor *borderColor;//边框颜色
@property (nonatomic, assign) IBInspectable   CGFloat  borderWidth;//边框宽度
@property (nonatomic, copy) IBInspectable NSString *propertyName;
@property (nonatomic, copy) IBInspectable NSString *bgColorAPI;
@end
  
// label
@interface UILabel (PYBaseBuildCodeXIB)
@property (nonatomic, copy) IBInspectable NSString *textColorAPI;
@property (nonatomic, copy) IBInspectable NSString *textAPI;
@end

// image
@interface UIButton (PYBaseBuildCodeXIB)
@property (nonatomic, copy) IBInspectable NSString *textColorAPI;
@property (nonatomic, copy) IBInspectable NSString *textAPI;
@end

// image
@interface UIImageView (PYBaseBuildCodeXIB)
@property (nonatomic, copy) IBInspectable NSString *imageAPI;
@end
image.png

XIB 解析

HTML解析:XIB会生成一个HTML文件,解析HTML使用的是xml.dom.minidom三方库,

常量字符存储:HTML中特定的标签字段由iOSXIBDomParserStaticStr.py来存储

解析model:

有基类iOSXIBDomParserButtonModel来处理View的一些基本属性记录,比如 borderColor、布局相关数据等

子类记录特有的属性值

image.png

使用

iOSXIBDomParser ,构造函数传入xib绝对路径,调用viewModel.convertToDic函数来解析成字典

parser = iOSXIBDomParser(path)
contentDict = parser.viewModel.convertToDic()

Json 生成Objective-c代码

代码生成的思路步骤

image.png

1、 解析Json,获取json中的属性定义列表、赋值子视图网络数据列表、懒加载视图属性列表、布局数据列表

时机开发中,我们经常使用宏定义来创建UIColor、UIFont,所以工具提供了colorConfig.txt、fontConfig.txt文件来配置创建规则

colorConfig.txt
 {
     "annotation_NetApiCreateColor": "根据字段创建UIColor对象,'#colorName#' 为字段名",
     "NetApiCreateColor":"[UIColor : colorWithName: #colorName#]",
     "annotation_DefineHexCreateColor": "根据宏定义创建UIColor对象,'#colorName#' 为16进制参数",
     "DefineHexCreateColor":"ColorDefine(#colorName#)",
     "annotation_StaticCreateColorList": "默认宏定义UIColor对象数组,key为宏定义,value为16进制颜色",
     "DefineCreateColorList": [
         "define_red":"0xFFFF0000"
     ]
 }

fontConfig.txt
{
        "annotation_DefineCreateFont": "根据字体名创建UIFont对象,'#FontSize#' 会替换成float类型",
        "DefineCreateFont": {

            "PingFangSC-Regular": "FontPingFangSCR(#fontSize#)",
            "PingFangSC-Medium": "FontPingFangSCM(#fontSize#)",
            "PingFangSC-Light": "FontPingFangSCL(#fontSize#)",
        },
        "annotation_CreateFont": "根据family_name创建UIFont对象,'#familyName#' 为font名, #fontSize#为size",
        "CreateFont": "[UIFont fontWithName:#familyName# size:#fontSize#]",
}

2、 根据模板文件,把对应的数据生成代码,插入到模板代码对应的位置中

在模板代码中,插入对应的关键字,使用正则来匹配对应的位置,具体代码参见:IOSTemplateRegulars.py

3、 格式化代码格式:ios_code_style.py

4、 输出view/viewModel文件

在输出文件的时候,需要标注文件头信息以及存储的位置,提供了rootConfig.text来进行配置

{
         "template_userNameKey": "名称",
         "template_nickNameKey": "昵称",

         "baseViewModelName": "viewModel的父类",
         "dataSouceName": "view持有的ViewModel属性名",

         "templateViewName": "模板View名",
         "templateBaseViewName": "模板view父类名",
         "templateViewLayoutPointerName":"模板view承载子视图的view属性名",

         "templateViewModelName": "模板ViewModel名",
         "templateBaseViewModelName": "模板ViewModel父类名",

         "templateViewPath": "模板view的路径",
         "templateViewModelPath": "模板ViewModel路径",

         "savePath": "生成的代码存储路径"

     }

生成之后的头文件目录为

代码生成工具的代码结构

使用:

步骤:

1、 创建一个Objective-c项目,把目录中的PYBaseBuildCodeXIBiOSTemplate文件夹拖入项目中

2、 创建xib文件,并布局视图、 xib文件右边填写各个子视图的参数:api、propertyName...

3、 找到ios_code_builder.py文件运行man函数

4、 配置弹出的colorConfig.text、 fontConfig.text、rootConfig.text文件

5、 在控制台回车,后完成代码转化

事例:


image.png

生成的cell.m文件

//
//  PYXIBViewCell
//  生成View
//  Created by 李鹏跃 on 2024/1/21.
//  Copyright © 2024 lpy. All rights reserved.
//  


#import "PYXIBViewCell.h"

@interface PYXIBViewCell()

@property (nonatomic,strong) UILabel *titleLabel;
@property (nonatomic,strong) UILabel *subTitle;
@property (nonatomic,strong) UIImageView *coverImage;
@property (nonatomic,strong) UIButton *byButton;

@end

@implementation PYXIBViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        [self setupViews];
    }
    return self;
}

- (void)didSetBaseViewModel:(iOSTemplateTableBaseViewModel *)baseViewModel {
    if (![baseViewModel isKindOfClass:PYXIBViewCellViewModel.class]) {
        return;
    }
    self.viewModel = (PYXIBViewCellViewModel *)baseViewModel;
}

- (void) setViewModel:(PYXIBViewCellViewModel *)viewModel {
    _viewModel = viewModel;
    
    // titleLabel
    self.titleLabel.text = self.viewModel.title;
    self.titleLabel.textColor = [UIColor py_colorWithHex: self.viewModel.titleColor ?: @"0xFAFAFA"];
                  
    // subTitle
    self.subTitle.text = self.viewModel.subTitle;
    self.subTitle.textColor = [UIColor py_colorWithHex: self.viewModel.subTitleColor ?: @"0xFAFAFA"];
                  
    // coverImage
    [self.coverImage sd_setImageWithURL:[NSURL URLWithString:self.viewModel.cover?:@""]];

}

- (void)setupViews {
    
    [self.contentView addSubview:self.titleLabel];
    [self.contentView addSubview:self.subTitle];
    [self.contentView addSubview:self.coverImage];
    [self.contentView addSubview:self.byButton];

    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@(17));
        make.top.equalTo(self.coverImage.mas_top);
        make.left.equalTo(self.coverImage.mas_right).offset(8);
        make.right.lessThanOrEqualTo(@(-16));
    }];
    [self.subTitle mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@(14));
        make.top.equalTo(self.titleLabel.mas_bottom).offset(8);
        make.left.equalTo(self.titleLabel.mas_left);
    }];
    [self.coverImage mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.equalTo(@(60));
        make.height.equalTo(@(60));
        make.top.equalTo(self.contentView.mas_top).offset(10);
        make.left.equalTo(self.contentView.mas_left).offset(16);
    }];
    [self.byButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@(44));
        make.width.equalTo(@(44));
        make.right.equalTo(@(-16));
        make.bottom.equalTo(self.contentView);
    }];
}

// MARK: - getter && setter

- (UILabel *) titleLabel {
    if (!_titleLabel) {
        _titleLabel = [[UILabel alloc]init];
        _titleLabel.layer.borderColor = KColorRGB(0xFFFF00FF).CGColor;
        _titleLabel.layer.borderWidth = 1;
        _titleLabel.layer.cornerRadius = 2;
        _titleLabel.textColor = KColorRGB(0xFF222222);
        _titleLabel.font = KFontR(12);
        _titleLabel.textAlignment = NSTextAlignmentLeft;
        _titleLabel.text = @"titleLabel";
    }
    return _titleLabel;
}

- (UILabel *) subTitle {
    if (!_subTitle) {
        _subTitle = [[UILabel alloc]init];
        _subTitle.textColor = KColorRGB(0x8032ADE6);
        _subTitle.font = KFontR(10);
        _subTitle.textAlignment = NSTextAlignmentLeft;
        _subTitle.text = @"subTitle";
    }
    return _subTitle;
}

- (UIImageView *) coverImage {
    if (!_coverImage) {
        _coverImage = [[UIImageView alloc]init];
        _coverImage.layer.cornerRadius = 4;
    }
    return _coverImage;
}
- (UIButton *) byButton {
    if (!_byButton) {
        _byButton = [[UIButton alloc]init];
        _byButton.layer.borderColor = KColorRGB(0xFFEB0159).CGColor;
        _byButton.layer.borderWidth = 1;
        _byButton.layer.cornerRadius = 2;
        [_byButton setTitleColor:KColorRGB(0xFFEB0159) forState:UIControlStateNormal];
        _byButton.titleLabel.font = KFontR(12);
        [self.byButton setTitle:@"购买" forState: UIControlStateNormal];
        [_byButton addTarget:self action:@selector(click_byButton) forControlEvents:UIControlEventTouchUpInside];
    }
    return _byButton;
}
- (void)click_byButton {
        
}

// MARK: - containerHeight
+ (CGFloat)getContainerViewHeightWithViewModel:(iOSTemplateTableBaseViewModel *)viewModel {
    if (![viewModel isKindOfClass:PYXIBViewCellViewModel.class]) {
        return CGFLOAT_MIN;
    }
    PYXIBViewCellViewModel *vm = (PYXIBViewCellViewModel *)viewModel;
    CGFloat h = CGFLOAT_MIN;
    return h;
}


@end

viewModel.h文件

//
//  PYXIBViewCellViewModel
//  生成View
//  Created by 李鹏跃 on 2024/1/21.
//  Copyright © 2024 lpy. All rights reserved.
//  


#import "iOSTemplateBaseViewModel.h"

NS_ASSUME_NONNULL_BEGIN

@interface PYXIBViewCellViewModel : iOSTemplateBaseViewModel
@property (nonatomic,copy) NSString *titleColor;
@property (nonatomic,copy) NSString *title;
@property (nonatomic,copy) NSString *subTitleColor;
@property (nonatomic,copy) NSString *subTitle;
@property (nonatomic,copy) NSString *cover;

@end

NS_ASSUME_NONNULL_END

为了学习Python3.9,我构思了这个Python生成Objective-c代码项目,以项目来推动学习,让学习更有动力,学习成果更加扎实。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容