从知道ReactiveCocoa开始就发现对这个库有不同的声音,上次参加<T>技术沙龙时唐巧对在项目中已全面使用FRP的代码家提出为什么这种编程模型出现了这么长时间怎么像ReactiveCocoa这种完全按FRP编写的库没能够流行起来这个问题。对这个问题的回答一般都是门槛高,解决方法就是培训和通过熟悉以前的代码来快速入门。其实在我学习的过程中也发现确实会有这个问题,不过就算是有这样那样问题使得ReactiveCocoa这样的库没法大面积使用起来,也不能错失学习这种编程思想的机会。
如果不用这样的库,能不能将这种库的编程思想融入项目中,发挥出其优势呢?答案是肯定的。
FRP全称Function Reactive Programming,从名称就能够看出来这个模型关键就是Function Programming和Reactive Programming的结合。那么就先从函数式编程说起。说函数式编程前先聊聊链式编程,先看看一个开源Alert控件的头文件里定义的接口方法的写法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* * 自定义样式的alertView * */ + (instancetype)showAlertWithTitle:(NSString *)title message:(NSString *)message completion:(PXAlertViewCompletionBlock)completion cancelTitle:(NSString *)cancelTitle otherTitles:(NSString *)otherTitles, ... NS_REQUIRES_NIL_TERMINATION; /* * @param otherTitles Must be a NSArray containing type NSString, or set to nil for no otherTitles. */ + (instancetype)showAlertWithTitle:(NSString *)title contentView:(UIView *)view secondTitle:(NSString *)secondTitle message:(NSString *)message cancelTitle:(NSString *)cancelTitle otherTitles:(NSArray *)otherTitles btnStyle:(BOOL)btnStyle completion:(PXAlertViewCompletionBlock)completion; |
库里还有更多这样的组合,这么写是没有什么问题,无非是为了更方便组合使用而啰嗦了点,但是如果现在要添加一个AttributeString,那么所有组合接口都需要修改,每次调用接口方法如果不需要用Attribuite的地方还要去设置nil,这样会很不易于扩展。下面举个上报日志接口的例子。
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 |
@interface SMLogger : NSObject //初始化 + (SMLogger *)create; //可选设置 - (SMLogger *)object:(id)obj; //object对象记录 - (SMLogger *)message:(NSString *)msg; //描述 - (SMLogger *)classify:(SMProjectClassify)classify; //分类 - (SMLogger *)level:(SMLoggerLevel)level; //级别 //最后需要执行这个方法进行保存,什么都不设置也会记录文件名,函数名,行数等信息 - (void)save; @end //宏 FOUNDATION_EXPORT void SMLoggerDebugFunc(DCProjectClassify classify, DCLoggerLevel level, NSString *format, ...) NS_FORMAT_FUNCTION(3,4); //debug方式打印日志,不会上报 #define SMLoggerDebug(frmt, ...) \ do { SMLoggerDebugFunc(SMProjectClassifyNormal,DCLoggerLevelDebug,frmt, ##__VA_ARGS__);} while(0) //简单的上报日志 #define SMLoggerSimple(frmt, ...) \ do { SMLoggerDebugFunc(SMProjectClassifyNormal,SMLoggerLevelDebug,frmt, ##__VA_ARGS__);} while(0) //自定义classify和level的日志,可上报 #define SMLoggerCustom(classify,level,frmt, ...) \ do { SMLoggerDebugFunc(classify,level,frmt, ##__VA_ARGS__);} while(0) |
从这个头文件可以看出,对接口所需的参数不用将各种组合一一定义,只需要按照需要组合即可,而且做这个日志接口时发现后续维护过程中会增加越来越多的功能和需要更多的input数据。比如每条日志添加应用生命周期唯一编号,产品线每次切换唯一编号这样需要在特定场景需要添加的input支持。采用这种方式会更加易于扩展。写的时候会是[[[[DCLogger create] message:@”此处必改”] classify:DCProjectClassifyTradeHome] save]; 这样,对于不是特定场所较通用的场景可以使用宏来定义,内部实现还是按照前者的来实现,看起来是[DCLogger loggerWithMessage:@”此处必改”];,这样就能够同时满足常用场景和特殊场景的调用需求。
有了链式编程这种易于扩展方式的编程方式再来构造函数式编程,函数编程主要思路就是用有输入输出的函数作为参数将运算过程尽量写成一系列嵌套的函数调用,下面我构造一个需求来看看函数式编程的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
typedef NS_ENUM(NSUInteger, SMStudentGender) { SMStudentGenderMale, SMStudentGenderFemale }; typedef BOOL(^SatisfyActionBlock)(NSUInteger credit); @interface SMStudent : NSObject 和通过熟悉以前的代码来快速入门。其实在我学习的过程中也发现确实会有这个问题,不过就算是有这样那样问题使得ReactiveCocoa这样的库没法大面积使用起来,也不能错失学习这种编程思想的机会。
如果不用这样的库,能不能将这种库的编程思想融入项目中,发挥出其优势呢?答案是肯定的。 FRP全称Function Reactive Programming,从名称就能够看出来这个模型关键就是Function Programming和Reactive Programming的结合。那么就先从函数式编程说起。说函数式编程前先聊聊链式编程,先看看一个开源Alert控件的头文件里定义的接口方法的写法。
库里还有更多这样的组合,这么写是没有什么问题,无非是为了更方便组合使用而啰嗦了点,但是如果现在要添加一个AttributeString,那么所有组合接口都需要修改,每次调用接口方法如果不需要用Attribuite的地方还要去设置nil,这样会很不易于扩展。下面举个上报日志接口的例子。
从这个头文件可以看出,对接口所需的参数不用将各种组合一一定义,只需要按照需要组合即可,而且做这个日志接口时发现后续维护过程中会增加越来越多的功能和需要更多的input数据。比如每条日志添加应用生命周期唯一编号,产品线每次切换唯一编号这样需要在特定场景需要添加的input支持。采用这种方式会更加易于扩展。写的时候会是[[[[DCLogger create] message:@”此处必改”] classify:DCProjectClassifyTradeHome] save]; 这样,对于不是特定场所较通用的场景可以使用宏来定义,内部实现还是按照前者的来实现,看起来是[DCLogger loggerWithMessage:@”此处必改”];,这样就能够同时满足常用场景和特殊场景的调用需求。 有了链式编程这种易于扩展方式的编程方式再来构造函数式编程,函数编程主要思路就是用有输入输出的函数作为参数将运算过程尽量写成一系列嵌套的函数调用,下面我构造一个需求来看看函数式编程的例子。
|