本篇是答应在端午写iOS网络-四篇源码解析以及封装的最后一篇,是针对上一篇YTKNetwork源码解析后的一次封装,也是自己实际项目中所使用过的。在对YTKNetwork封装的时候,还是需要对YTKNetwork源码进行了解,方便对此封装的理解,请读一下:https://www.cnblogs.com/guohai-stronger/p/9194519.html
本篇是实际工作过项目网络架构抽出来的,读完大约15-25分钟左右,Demo也会上传到github。(暂没有批量请求需求)
一、代码结构如下
1.针对YTKNetwork网络封装目录
2.项目代码结构与使用:举例购物车列表
二、准备
1.新建项目,导入AFNetworking,YTKNetwork(暂用cocoapods)。
1)通过命令行cd 新建项目地址(整个直接拖拽到终端),
2)进入项目输入vim Podfile
3)输入i,进入编辑模式
platform :ios, '8.0' target 'TestYTK' do pod 'AFNetworking' pod 'YTKNetwork' pod 'YYModel' pod 'Toast' end
4)然后按Esc键,并且输入“ :”号进入vim命令模式,在冒号后边输入wq
5)pod install
重新编译一下。 (最好建立一个pch文件,便于管理)
2.将代码直接拖入项目中
将标红的代码拖入项目中,编译一下!
三、代码分析
1 . IOANotificationManager(通知)
主要作用:主要是监听网络的变化。
#import <Foundation/Foundation.h> extern const NSString *kNotNetworkNotificationKey; @interface IOANotificationManager : NSObject // 无网络 + (void)postNoNetworkNotification:(NSDictionary *)userInfo; // 无网络 + (void)addNoNetworkBoserver:(id)target selector:(SEL)selector; + (void)removeObservers:(id)target; @end
.m实现如下:
#import "IOANotificationManager.h" const NSString *kNotNetworkNotificationKey = @"com.ioa.NoNetwork"; @implementation IOANotificationManager + (void)postNoNetworkNotification:(NSDictionary *)userInfo { [[NSNotificationCenter defaultCenter] postNotificationName:(NSString *)kNotNetworkNotificationKey object:nil userInfo:userInfo]; } // 无网络 + (void)addNoNetworkBoserver:(id)target selector:(SEL)selector { if (target) { [[NSNotificationCenter defaultCenter] addObserver:target selector:selector name:(NSString *)kNotNetworkNotificationKey object:nil]; } } + (void)removeObservers:(id)target { [[NSNotificationCenter defaultCenter] removeObserver:target]; } @end
>>>拓展
其实在这里面也可以做用户登陆,退出登陆等监听操作。
2. IOARequest
主要作用:定义一些请求状态码、响应码,发起请求等
IOARequest.h
#import <YTKNetwork.h> #import "IOAApiManager.h" //管理用户信息 //#import "IOADataManager.h" #import "IOANotificationManager.h" #import "IOAResponse.h" @interface IOARequest : YTKRequest //返回接口状态码,其中:200 成功, // 600 未登录 // 500 服务器错误 // 501 已经存在 // 502 数据接口为空 // 400 请求参数有错, // 401 非法请求, // 1 没有网络 // 0 服务后台问题,可使用response的statuscode查询具体问题 @property (nonatomic, readonly, assign) NSInteger serverResponseStatusCode; //返回请求状态码,其中:1正常,0不正常 @property (nonatomic, readonly, assign) NSInteger serverRequestStatusCode; // 返回的提示信息 @property (nonatomic, readonly, copy) NSString *serverResponseMessage; // 如果没有网络 failure同步方式返回 - (void)startWithCompletionBlockWithSuccess:(YTKRequestCompletionBlock)success failure:(YTKRequestCompletionBlock)failure;
通过上面发现IOARequest是继承YTKRequest,以后我们在每一个模块请求数据的时候,就继承我们自己的IOARequest。
返回接口状态码以及请求码是根据我们后台自己定义的,大家可以根据自己的实际情况进行更改。
2. IOARequest.m
部分代码:
- (NSTimeInterval)requestTimeoutInterval { //请求限时 return 30.0; } - (YTKRequestMethod)requestMethod { //测试环境,使用YTKRequestMethodGET,便于与后台和测试调试问题 #ifdef DEBUG return YTKRequestMethodGET; #else return YTKRequestMethodPOST; #endif } - (void)startWithCompletionBlockWithSuccess:(YTKRequestCompletionBlock)success failure:(YTKRequestCompletionBlock)failure { if (![IOAApiManager isNetworkReachable]) { self.serverResponseStatusCode = 1; // 没网络 [IOANotificationManager postNoNetworkNotification:nil]; if (failure) { failure(self); } return; } // WS(weakSelf); [self setCompletionBlockWithSuccess:success failure:^(__kindof YTKBaseRequest * _Nonnull request) { if (failure) { failure(request); // return; } }]; //发起请求 [self start]; } - (BOOL)statusCodeValidator { //判断响应状态码 BOOL isOk = [super statusCodeValidator]; if (!isOk) { #if DEBUG [self testAlertInfo:@"网络请求错误"]; #endif return isOk; } if (!self.responseObject) { self.serverResponseStatusCode = 0; return NO; } self.serverResponseStatusCode = [self.responseObject[@"ret"] integerValue]; self.serverRequestStatusCode = [self.responseObject[@"code"] integerValue]; self.serverResponseMessage = self.responseObject[@"msg"]; if (self.serverResponseStatusCode == 200) { return YES; } else if (self.serverResponseStatusCode > 400 && self.serverResponseStatusCode < 500) { [IOAApiManager saveToken:nil]; //移除用户个人信息 // [IOADataManager removeUserInfo]; return NO; } return NO; }
3.IOAUploadRequest
主要负责:图片的上传和下载(我们项目上传图片,后台返回是一个对象,对象包括如下)。
#import "IOARequest.h" // 上传图片返回的模型 @interface IOAUploadResponseModel : NSObject @property (nonatomic, copy) NSString *url; @property (nonatomic, copy) NSString *file; @property (nonatomic, copy) NSString *file_name; @end //可以直接IOARequest,不需要继承YTKRequest @interface IOAUploadRequest : IOARequest @property (nonatomic, strong) UIImage *image; //获取上传进度 @property(nonatomic, copy) void(^uploadProgressBlock)(IOAUploadRequest *currentApi, NSProgress * progress); @end
在.m里面以文件上传方式上传
#define WS(weakSelf) __weak __typeof(&*self)weakSelf = self @implementation IOAUploadResponseModel @end @implementation IOAUploadRequest - (YTKRequestMethod)requestMethod { return YTKRequestMethodPOST; } //设置上传图片 所需要的 HTTP HEADER - (AFConstructingBlock)constructingBodyBlock { UIImage *image = self.image; return ^(id<AFMultipartFormData> formData) { NSData *data = UIImagePNGRepresentation(image); NSString *name = @"file"; NSString *fileName = @"upload"; NSString *type = @"image/png"; [formData appendPartWithFileData:data name:name fileName:fileName mimeType:type]; }; } #pragma mark 上传进度 - (AFURLSessionTaskProgressBlock) resumableUploadProgressBlock { WS(weakSelf); AFURLSessionTaskProgressBlock block = ^void(NSProgress * progress){ if (_uploadProgressBlock) { _uploadProgressBlock(weakSelf, progress); } }; return block; } @end
4.IOANetworkManager
主要负责网络状态的管理,监听。
5.IOAResponse
主要负责后台返回状态码管理,包括:是否有网络,token是否失效,服务器错误以及参数错误等。
IOAResponse.h
typedef NS_ENUM(NSInteger, ResponseStatusType) { kResponseStatusTypeRequestError = 0, // 服务后台问题 kResponseStatusTypeNoNetwork = 1, // 没有网络 kResponseStatusTypeSuccess = 200, kResponseStatusTypeExpiryToken = 401, kResponseStatusTypeServerServiceError = 500, // kResponseStatustypeServiceExist = 501, kResponseStatusTypeDataNull = 502, kResponseStatusTypeNotLogin = 600, };
@property (nonatomic, assign) BOOL success; //返回接口状态码,其中:200 成功, // 600 未登录 // 500 服务器错误 // 501 已经存在 // 502 数据接口为空 // 400 请求参数有错, // 401 非法请求, // 1 没有网络 // 0 服务后台问题,可使用response的statuscode查询具体问题 @property (nonatomic, assign) ResponseStatusType responseStatusType; @property (nonatomic, assign) NSInteger serverResponseStatusCode; // 服务端返回的status code @property (nonatomic, assign) NSInteger requestResponseStatusCode; // 请求返回的status code @property (nonatomic, strong) id responseObject; @property (nonatomic, copy) NSString *responseMessage; + (IOAResponse *)responseWithRequest:(IOARequest *)request; - (void)updateStatusCodesWithRequest:(IOARequest *)request; // 是否需要提示 - (BOOL)alertOrNot; // 是否没有有网络 - (BOOL)isNoNetwork; // 是否token失效 - (BOOL)isExpiryToken; // 服务器错误 - (BOOL)isRequestServerError; // 后台服务错误 - (BOOL)isServerServiceError;
IOAResponse.m是其赋值,查看demo即可。
6.IOAApiManager
主要任务:负责是管理Api,开发环境,证书,接口参数,token等。
IOAApiManager.h
+ (void)configNetwork; //+ (NSString *)getService; //+ (NSString *)getToken; + (NSMutableDictionary *)getCommomParametersWith:(NSString *)service token:(NSString *)token; + (NSMutableDictionary *)getParametersWithService:(NSString *)service; + (void)startNetworkMonitoring; + (void)stopNetworkMonitoring; + (BOOL)isNetworkReachable; + (AFNetworkReachabilityStatus)getNetworkStatus; + (void)saveToken:(NSString *)token; + (NSString *)getToken;
在IOAApiManager.m
typedef NS_ENUM(NSUInteger, ServerType) { kSeverTypeDev, // 开发服务器地址 kSeverTypeTest, //测试服务器地址 kSeverTypeRelease //发布版服务器地址 }; @implementation IOAApiManager + (void)configNetwork { YTKNetworkAgent *agent = [YTKNetworkAgent sharedAgent]; [agent setValue:[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"application/x-www-form-urlencodem", nil] forKeyPath:@"_manager.responseSerializer.acceptableContentTypes"]; static ServerType serverType = kSeverTypeRelease; #if DEBUG serverType = kSeverTypeDev; #else serverType = kSeverTypeRelease; #endif YTKNetworkConfig *config = [YTKNetworkConfig sharedConfig]; switch (serverType) { case kSeverTypeDev: // 开发服务器地址 //改成自己的 config.baseUrl = @"http://www.baidu.com"; break; case kSeverTypeTest: // 测试服务器地址 config.baseUrl = @"https://www.baidu.com"; break; case kSeverTypeRelease: // 发布版服务器地址 config.baseUrl = @"https://www.baidu.com"; break; default: break; } [self configHttps]; } + (void)configHttps { // 获取证书 NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ssl_content" ofType:@"pem"];//证书的路径 NSData *certData = [NSData dataWithContentsOfFile:cerPath]; // 配置安全模式 YTKNetworkConfig *config = [YTKNetworkConfig sharedConfig]; // config.cdnUrl = @""; // 验证公钥和证书的其他信息 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; // 允许自建证书 securityPolicy.allowInvalidCertificates = YES; // 校验域名信息 securityPolicy.validatesDomainName = YES; // 添加服务器证书,单向验证; 可采用双证书 双向验证; securityPolicy.pinnedCertificates = [NSSet setWithObject:certData]; [config setSecurityPolicy:securityPolicy]; }
上面的域名要改成自己的域名,上面是以baidu为准啦!!!
四、实际使用
1. 这个项目是以MVVM模式进行搭建。
在Api文件夹写接口参数
在viewModel里面写接口的请求以及解析
在Datas里面放的是plist文件等。
这样便于根据不同功能进行管理
2.Api文件夹
Api.h
Api.m,利用YYModel进行将声明的model转为字典,作为参数
3.ViewModel
ViewModel.h声明方法,请求方法
在ViewModel.m实现其方法
4.最后在控制器里面调用请求方法
4.1、导入ViewModel所在的类名
4.2、声明属性并懒加载
4.3、控制器调用请求方法
上面就是YTKNetwork的封装使用了,demo里面只有封装的代码,使用必须要真实的接口,(假数据没有必要)。如果有需要对YTKNetwork进行二次封装,可以下载github,然后按照这个使用方法就可以进行网络请求和封装啦。
demo地址:https://github.com/zxy1829760/YTKNetwork-
到现在为止,四天关于网络请求的内容四篇博客就大致说完了,欢迎大家指正!!!