前言
去model化
是一种框架设计上的做法,其中的model
并不是指架构中的model
层,套用Casa大神博客中的原文就是:
model化就是使用数据对象,去model化就是不使用数据对象。
常见的去model化
做法是使用字典保存数据信息,然后提供一个reformer
负责将这些字典数据转换成View
层可展示的信息,其流程图如下:
更详细的理论知识可以看Casa大神的去model化和数据对象。本文基于Casa大神的实践基础使用另外一种去model化
的实现方式。
使用背景
在很早之前就看过大神的文章,不过一直没有去尝试这种做法。在笔者最近跳入新坑之后,总算是有了这么一次机会。需求是存在着三个非常相似的cell
,但分别对应着不同的数据model
:
总结三个cell
都需要的展示数据包括:
- 产品名称
- 使用条件
- 截止日期
- 背景图片
此外,优惠信息
属于第一个和第二个独有的。现在这一需求存在的问题主要有这么三点:
三种数据对象在服务器返回的属性字段中命名差别大
这是大部分的应用都存在的一个问题,但是本文中的数据对象有一个显著的特点是它们对应显示的cell
存在很大的相似度,可以被转换成相似的展示数据三种
cell
可以封装成一种,却分别对应着不同的数据对象
这里涉及cell
和数据对象的对接问题,如果cell
在以后发生改变了,那么原有的数据对象是否还能适用控制器需要在数据源方法中调配不同的
cell
和model
,耦合过大
这个也是常见的问题之一,通常可以考虑适用工厂模式将调配的业务分离出去,但在本文中采用去model
的方式实现
这些问题都有可能导致项目后期维护的过程中变得难以修改,小小的需求改动都会导致代码的大改。笔者的解决方式是制定cell
和model
之间对应的两个协议,从而控制器无需理会两者的具体类型。
实现
我在上一篇文章MVC架构杂谈中提到过M
层的业务逻辑放在model
中,虽然本文要去model化
,但只是去除属性对象,自身的逻辑处理还保留着。下面是笔者去model化
的协议图以及协议声明属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@protocol LXDTicketModelProtocol @optional @property (nonatomic, readonly) NSAttributedString * perferential; @required @property (nonatomic, readonly) NSString * backgroundImageName; @property (nonatomic, readonly) NSString * goodName; @property (nonatomic, readonly) NSString * effectCondition; @property (nonatomic, readonly) NSString * deadline; @property (nonatomic, readonly) LXDCellType type; - (instancetype)initWithDict: (NSDictionary *)dict; @end @protocol KMCTicketCellProtocol - (void)configurateCellWithModel: (id)model; @end |
对于本文之中这种存在共同显示效果的model
,可以声明一个包含多个readonly
属性的协议,让这些模型对象在协议的getter
方法中执行数据->展示
这一过程的业务逻辑,而model
自身只需简单的持有字典数据即可:
以LXDCouponTicketModel
为例,协议的实现代码如下:
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
// h文件 @interface LXDCouponTicketModel: NSObject @end // m实现 @implementation LXDCouponTicketModel { NSDictionary * _dict; } - (NSString *)backgroundImageName { return ([_dict[@"overdue"] boolValue] ? @"coupon_overdue" : @"coupon_common"); } - (NSAttributedString *)perferential { NSAttributedString * result = objc_getAssociatedObject(self, KMCPerferentialKey); if (result) { return result; } NSMutableAttributedString * attributedString = [[NSMutableAttributedString alloc] initWithString: @"¥" attributes: @{ NSFontAttributeName: [UIFont systemFontOfSize: 16] }]; [attributedString appendAttributedString: [[NSAttributedString alloc] initWithString: [NSString stringWithFormat: @"%g", [_dict[@"ticketMoney"] doubleValue]] attributes: @{ NSFontAttributeName: [UIFont boldSystemFontOfSize: 32] }]]; [attributedString addAttributes: @{ NSForegroundColorAttributeName: KMCCommonColor } range: NSMakeRange(0, attributedString.length)]; result = attributedString.copy; objc_setAssociatedObject(self, KMCPerferentialKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); te> model化就是使用数据对象,去model化就是不使用数据对象。 常见的 更详细的理论知识可以看Casa大神的去model化和数据对象。本文基于Casa大神的实践基础使用另外一种 使用背景在很早之前就看过大神的文章,不过一直没有去尝试这种做法。在笔者最近跳入新坑之后,总算是有了这么一次机会。需求是存在着三个非常相似的 总结三个
此外,
这些问题都有可能导致项目后期维护的过程中变得难以修改,小小的需求改动都会导致代码的大改。笔者的解决方式是制定 实现我在上一篇文章MVC架构杂谈中提到过
对于本文之中这种存在共同显示效果的 以
|