内容简介:首先我简单的说一下,RAC、MVVM 是啥。RAC:即ReactiveCocoa 是一套函数式编程的框架,的确很好用,可以节省很多开发时间。当下Swift也提供很多类似的高阶函数,学习一下还是很有必要的,我这里给几个链接有兴趣的可以看一下。MVVM:由MVC演变而来的,为Controller 减负的设计模式。
首先我简单的说一下,RAC、MVVM 是啥。
RAC:即ReactiveCocoa 是一套函数式编程的框架,的确很好用,可以节省很多开发时间。当下Swift也提供很多类似的高阶函数,学习一下还是很有必要的,我这里给几个链接有兴趣的可以看一下。
MVVM:由MVC演变而来的,为Controller 减负的设计模式。
RAC在MVVM设计中,充当胶水的角色。
1、数据绑定:作用View和ViewModel之间,但ViewModel中数据因为用户的操作变化时,View更改马上更新。 2、网络请求: 把网络请求封装成Command,在View层触发网络访问 3、Model 数据变化的时候,更新ViewModel数据
逻辑关系请看下图:
rac.png
这里只是简单的描述了一下RAC+MVVM,下面重点介绍一下其中网络请求的部分。在实际开发过程中,网络请求部分与以前的block后调方式有细微的差别。我这里用信号的方式返回数据,View层,通过Command 命令订阅返回数据,这里封装成了一个工具:FMARCNetwork( https://github.com/zhufaming/ZFMRACNetwork )
简单的思维导图:
shiwei.png
工具使用的主要三方框架:
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' target 'ZFMRACNetwork' do #AFN -->不解释 pod 'AFNetworking' #ReactiveCoca --> ReactiveCocoa 对OC的支持 pod 'ReactiveObjC', '~> 3.1.0' #网络提示--> 网络监听显示,主要是展示状态 pod 'JDStatusBarNotification', '~> 1.5.6' #提示 -->主要的提示库 pod 'MBProgressHUD', '~> 1.1.0' end
项目结构:
jiegou.png
ZFMRACNetworkTool.h : 工具引用.h文件,使用工具,#import 一下就可以了 FMHttpConstant.h 网络请求相关的宏定义 FMHttpRequest.h 请求相关的参数配置 FMHttpResonse.h 网络请求响应的,信号返回的数据模型 FMARCNetwork 网络请求主要的 工具 类
单例设计工具类:
@interface FMARCNetwork : NSObject +(instancetype) sharedInstance; /** 网络请求,返回信号 按照, FMHttpRequest 参数化设置 @param req FMHttpRequest @return RACSignal */ - (RACSignal *)requestNetworkData:(FMHttpRequest *)req; /** 网络请你,简便方案 @param path 请求路径 --- 基本链接,请在 FMHttpRConstant.h 文件中设置 @param params 参数字典 @return RACSignal */ - (RACSignal *)requestSimpleNetworkPath:(NSString *)path params:(NSDictionary *)params; /** 文件上传、可以当个文件、也可以多个文件 @param path 文件上传服务器地址,这里单独给出来,是因为很大部分图片服务器和业务服务器不是同一个 @param params 参数 没有可传 @{} @param fileDatas NSData 数组 @param name 指定数据关联的名称 @return RACSignal */ - (RACSignal *)uploadNetworkPath:(NSString *)path params:(NSDictionary *)params fileDatas:(NSArray <nsdata nbsp=""> *)fileDatas name:(NSString *)name mimeType:(NSString *)mimeType; @end </nsdata>
方法简介:
requestNetworkData : 通用请求,可以通过FMHttpRequest 配置请求的方式:Get or Post
requestSimpleNetworkPath: 简单的网络请求,传url 当然是字符串了,字典参数,默认Post 请求。这样设计的目的其实现在很少有用get 的请求了。
uploadNetworkPath: 文件或图片的上传。
实现:
- (RACSignal *)requestNetworkData:(FMHttpRequest *)req{ /// request 必须的有值 if (!req) return [RACSignal error:[NSError errorWithDomain:HTTPServiceErrorDomain code:-1 userInfo:nil]]; @weakify(self); /// 创建信号 RACSignal *signal = [RACSignal createSignal:^(id <racsubscriber> subscriber) { @strongify(self); /// 获取request //如果需要 额外的参数,请追加到参数字典里面去 //ExtendsParameters *exParams = req.extendsParameters; NSError *serializationError = nil; NSMutableURLRequest *request = [self.manager.requestSerializer requestWithMethod:req.method URLString:[[NSURL URLWithString:req.path relativeToURL:[NSURL URLWithString:BaseUrl] ] absoluteString] parameters:req.parameters error:&serializationError]; if (serializationError) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" dispatch_async(self.manager.completionQueue ?: dispatch_get_main_queue(), ^{ [subscriber sendError:serializationError]; }); #pragma clang diagnostic pop return [RACDisposable disposableWithBlock:^{ }]; } /// 获取请求任务 __block NSURLSessionDataTask *task = nil; task = [self.manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { @strongify(self); if (error) { NSError *parseError = [self errorFromRequestWithTask:task httpResponse:(NSHTTPURLResponse *)response responseObject:responseObject error:error]; NSInteger code = [parseError.userInfo[HTTPServiceErrorHTTPStatusCodeKey] integerValue]; NSString *msgStr = parseError.userInfo[HTTPServiceErrorDescriptionKey]; //初始化、返回数据模型 FMHttpResonse *response = [[FMHttpResonse alloc] initWithResponseError:parseError code:code msg:msgStr]; //同样也返回到,调用的地址,也可处理,自己选择 [subscriber sendNext:response]; //[subscriber sendError:parseError]; [subscriber sendCompleted]; //错误可以在此处处理---比如加入自己弹窗,主要是服务器错误、和请求超时、网络开小差 [self showMsgtext:msgStr]; } else { /// 判断 NSInteger statusCode = [responseObject[HTTPServiceResponseCodeKey] integerValue]; if (statusCode == HTTPResponseCodeSuccess) { FMHttpResonse *response = [[FMHttpResonse alloc] initWithResponseSuccess:responseObject[HTTPServiceResponseDataKey] code:statusCode]; [subscriber sendNext:response]; [subscriber sendCompleted]; }else{ if (statusCode == HTTPResponseCodeNotLogin) { //可以在此处理需要登录的逻辑、比如说弹出登录框,但是,一般请求某个 api 判断了是否需要登录就不会进入 //如果进入可一做错误处理 NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; userInfo[HTTPServiceErrorHTTPStatusCodeKey] = @(statusCode); userInfo[HTTPServiceErrorDescriptionKey] = @"请登录!"; NSError *noLoginError = [NSError errorWithDomain:HTTPServiceErrorDomain code:statusCode userInfo:userInfo]; FMHttpResonse *response = [[FMHttpResonse alloc] initWithResponseError:noLoginError code:statusCode msg:@"请登录!"]; [subscriber sendNext:response]; [subscriber sendCompleted]; //错误提示 [self showMsgtext:@"请登录!"]; }else{ NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; userInfo[HTTPServiceErrorResponseCodeKey] = @(statusCode); //取出服务给的提示 NSString *msgTips = responseObject[HTTPServiceResponseMsgKey]; //服务器没有返回,错误信息 if ((msgTips.length == 0 || msgTips == nil || [msgTips isKindOfClass:[NSNull class]])) { msgTips = @"服务器出错了,请稍后重试~"; } userInfo[HTTPServiceErrorMessagesKey] = msgTips; if (task.currentRequest.URL != nil) userInfo[HTTPServiceErrorRequestURLKey] = task.currentRequest.URL.absoluteString; if (task.error != nil) userInfo[NSUnderlyingErrorKey] = task.error; NSError *requestError = [NSError errorWithDomain:HTTPServiceErrorDomain code:statusCode userInfo:userInfo]; //错误信息反馈回去了、可以在此做响应的弹窗处理,展示出服务器给我们的信息 FMHttpResonse *response = [[FMHttpResonse alloc] initWithResponseError:requestError code:statusCode msg:msgTips]; [subscriber sendNext:response]; [subscriber sendCompleted]; //错误处理 [self showMsgtext:msgTips]; } } } }]; /// 开启请求任务 [task resume]; return [RACDisposable disposableWithBlock:^{ [task cancel]; }]; }]; return [signal replayLazily]; //多次订阅同样的信号,执行一次 } </racsubscriber>
如何使用:给一个简单的例子,也在项目中,详情请git
- (IBAction)correctAction:(UIButton *)sender { /// 1. 配置参数 NSMutableDictionary *easyDict = [NSMutableDictionary dictionary]; /// 2. 配置参数模型 #define MH_GET_LIVE_ROOM_LIST @"Room/GetHotLive_v2" FMHttpRequest *req = [FMHttpRequest urlParametersWithMethod:HTTTP_METHOD_POST path:@"Room/GetHotLive_v2" parameters:easyDict]; _reqSignal = [[FMARCNetwork sharedInstance] requestNetworkData:req]; [_reqSignal subscribeNext:^(FMHttpResonse *response) { if (response.isSuccess) { NSLog(@"--%@",response.reqResult); NSData *jsonData = [NSJSONSerialization dataWithJSONObject:response.reqResult options:NSJSONWritingPrettyPrinted error:nil]; NSString * str = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; self.textV.text = str; } }]; }
end@2x.png
首先感谢大家浏览此文章。
网络请求可以直接下载使用:如果对您有帮助,请求点赞或喜欢,如果你有个github 账号,请不吝给,谢谢。
作者:他们叫我朱老师
链接:https://www.jianshu.com/p/6da5faaaca86
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Java实现简单的站点请求模式
- 如何使用策略模式处理多种类型请求
- 常用设计模式/容器/依赖注入/静态代理/请求对象
- Reactor-Guice 0.0.8 发布 ,支持 API 网关模式、跨域请求
- Reactor-Guice 0.0.8 发布 ,支持 API 网关模式、跨域请求
- kafka集群Broker端基于Reactor模式请求处理流程深入剖析-kafka商业环境实战
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
网站运维技术与实践
饶琛琳 / 电子工业出版社 / 2014-3 / 69.00元
网站运维工作,一向以内容繁杂、覆盖面广著称。《网站运维技术与实践》选取日常工作涉及的监测调优、日志分析、集群规划、自动化部署、存储和数据库等方面,力图深入阐述各项工作的技术要点及协议原理,并介绍相关开源产品的实践经验。在技术之外,作者也分享了一些关于高效工作及个人成长方面的心得。 《网站运维技术与实践》适合Linux 系统管理员、中大型网站运维工程师及技术负责人、DevOps 爱好者阅读。同......一起来看看 《网站运维技术与实践》 这本书的介绍吧!