iOS中实现链式调用DSL的基本原理及举例

一 、什么是DSL

     DSL(Domain Specific Language) 翻译成中文就是:“领域特定语言”。首先,从定义就可以看出,DSL 也是一种编程语言,只不过它主要是用来处理某个特定领域的问题。
  下边介绍iOS中如何实现链式调用的DSL。

二、具体实现

   首先我们经常使用的**Masonry**便是这样处理的,下边一段代码:
// Masonry 
[view1 mas_makeConstraints:^(MASConstraintMaker *make) { 
    make.top.equalTo(superview.mas_top).with.offset(padding.top); 
    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); 
}]; 

更加简洁的,我们可以将中括号去掉,直接通过不间断的点语法来实现。
实现DSL的基本思想就是通过block传递需要的参数,并且返回对象本身,从而进一步点语法调用下一个属性。(返回本身就是写出属性的getter方法,通过例子可以很好地明白)。

在iOS中实现DSL,基本上实现三部分:
(1).首部创建
(2).中间的连接属性
(3).结尾返回

咱们实现一个UIButton的DSL,包含部分属性。我们经常使用的控件等都可以封装成这种DSL,可以方便我们使用。先看下边的这段代码:

[self.view addSubview: UIButton.
   creatButton.
   buttonUtil.
   titl(@"aaaa", UIControlStateNormal).
   frame(CGRectMake(10, 10, 200, 200)).
   buttonTyp(UIButtonTypeCustom)];

上述代码中的creatButton就是咱们的创建首部,中间的titl、frame就是中间的连接属性buttonTyp就是结尾返回
<1> 首先继承NSObject,将button的属性用block重写

#import <UIKit/UIKit.h>
@interface ButtonUtil : NSObject

/**
 通过Block传递需要的参数,然后返回值是ButtonUtil,可以继续调用下一个属性
 */
@property(nonatomic, weak,readonly)ButtonUtil * (^contentEdgInset)(UIEdgeInsets *contentEdgeInset);
@property(nonatomic, weak,readonly)ButtonUtil * (^showsTouchWhenHighlighte)(BOOL showsTouchWhenHighlighte);
@property(nonatomic, weak,readonly)ButtonUtil * (^tintColo)(UIColor * tintColo);
@property(nonatomic, weak,readonly)ButtonUtil * (^titl)(NSString * title, UIControlState  state);
@property(nonatomic, weak,readonly)ButtonUtil * (^titleColo)(UIColor * color, UIControlState  state);
@property(nonatomic, weak,readonly)ButtonUtil * (^shadowColo)(UIColor * color, UIControlState  state);
@property(nonatomic, weak,readonly)ButtonUtil * (^imag)(UIImage * image, UIControlState  state);
@property(nonatomic, weak,readonly)ButtonUtil * (^backgroundImag)(UIImage * image, UIControlState  state);
@property(nonatomic, weak,readonly)ButtonUtil * (^attributeTitle)(NSAttributedString * title, UIControlState  state);
@property(nonatomic, weak,readonly)ButtonUtil * (^frame)(CGRect rect);

/**
 结尾属性,返回值是UIButton,完成一个button的创建
 */
@property(nonatomic, weak,readonly)UIButton * (^buttonTyp)(UIButtonType typ);
@end

下边是.m文件的实现(没有全部实现仅仅是举例)

@interface ButtonUtil()
@property(nonatomic,strong)UIButton *button;
@end

@implementation ButtonUtil
-(ButtonUtil *(^)(CGRect))frame
{
    return  ^(CGRect frame)
    {
        self.button.frame =frame;
        return self;
    };
}

-(ButtonUtil *(^)(NSString *, UIControlState))titl
{
   return ^(NSString * str ,UIControlState state)
    {
        [self.button setTitle:str forState:state];
        return self;
    };
}

-(UIButton *(^)(UIButtonType))buttonTyp{

    return ^(UIButtonType type){
        
        return self.button;
    };
}


@end

<2>创建一个UIbutton的类别来实现首部的创建,可以使用button直接调用创建button的方法

@interface UIButton (utils)
@property(nonatomic,strong ,readonly) ButtonUtil * buttonUtil;

@property(class, nonatomic ,strong,readonly) UIButton * creatButton;
@implementation UIButton (utils)

static ButtonUtil *_maker = nil;
-(ButtonUtil *)buttonUtil{
    return _maker;
}

+(UIButton *)creatButton
{
    ButtonUtil * util =[[ButtonUtil alloc]init];
    _maker = util;
    _maker.button = [[UIButton alloc]init];
    return _maker.button;
}
@end

<1>中创建中间变量,返回的是ButtonUtil本身,可以继续调用其他属性;创建尾部结束语,返回的是UIbutton。

三、总结

(1)、基本上所有的控件都可以重新封装。
(2)、分开两个类优点就是清晰,谁的事谁干,可以防止.buttonUtil.buttonUtil.buttonUtil.buttonUtil这种。
(3)、这种链式调用能够使程序更加清晰,在特定场景下使程序的可读性更强。

还会逐步更改,写的时候有的地方感觉不是很连贯。可以参考代码一起看。链接地址:https://github.com/rainhand/iOS-DSL-chaine.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,124评论 19 139
  • 今天是我学习的第336篇文章,每天只字不差地阅读和必做的留言结果就是:短短不到一年的时间,我的生活已经产生了翻天覆...
    风筝有风007阅读 1,738评论 0 1
  • 今天带孩子来学游泳,正巧碰到一个孩子被妈妈推搡着进检票口。 孩子哭着说不去,还转过来身体往外走,结果妈妈面带微笑推...
    三目荷阅读 3,437评论 3 4
  • 【前言】在过去参加自品牌训练营的十天里,按照老师的要求进行了定位、平台、内容、传播、运营等一系列学习和实践。虽然在...
    Bookish_陈键阅读 3,060评论 0 2
  • 我是那个突破自我设限的叨叨 宁妈的分享从气势,从流畅与普通话的标准程度来说,不是我听过的课程当中最好的...
    叨叨有刀阅读 1,157评论 0 0

友情链接更多精彩内容