• YTKNetwork网络封装


    本篇是答应在端午写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-

    到现在为止,四天关于网络请求的内容四篇博客就大致说完了,欢迎大家指正!!!

  • 相关阅读:
    多库查询 sp_addlinkedserver使用方法(添加链接服务器)(转)片段整理
    利用asp.net路由实现url解析
    C#事务 访问数据库(转)
    男人30而立,30岁的男人喊起来!你们立了吗?
    c# 调用SQL Server存储过程返回值(转)
    转摘 JQUERY操作JSON例子
    jstree 从简单说起Jquery 插件应用说明
    利用反射对对象属性赋值取值操作
    asp.net 造成seesion 丢失的问题之一
    jquery 实现从左边listbox选择至右边listbox
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/9197575.html
Copyright © 2020-2023  润新知