对于iOS程序猿来说,AFNetworking
的强大之处,自然是不用言表,大家都早已深有体会。但是一般在使用这些第三方的时候,我们一般都会根据自己的使用习惯及业务功能需求进行封装处理,当然我也一样,对AFNetworking
进行了二次封装处理,所以此次发布出来仅供参考:
注意:使用该框架前,需要集成 AFNetworking 和 FMDB,因为该框架是基于这两者进行的二次封装
一:框架特点
1:基于AFNetworking
封装处理,简化了对AFNetworking
的直接操作,使调用更加方便简洁;
2:将AFNetworking
原有的两种回调方式拓展为了三种回调,并且支持用户根据服务器数据格式进行配置,功能细化,操作简单;
3:结合FMDB
封装了数据库,可以根据需要进行缓存网络数据;
4:集成了Delegate
和Block
两种网络回调方式,用户可以根据自己的喜好进行选择使用任意一种回调方式;
Demo链接:https://github.com/Kinglions/FrankNetworkManage
二:框架解析
(1)网络请求框架:
/**
* 网络请求封装
*/
#import
#import
#import
#import
#import "FrankNetworkMacro.h"
typedef void (^RequestPrepare)();
typedef void (^RequestFinally)();
/**
请求成功回调
@param task 请求对象
@param responseObject 响应数据
@param requestParams 请求参数
*/
typedef void (^ReplySucess)(NSURLSessionDataTask *task, id responseObject, NSDictionary* requestParams);
/**
请求失败回调
*/
typedef void (^ReplyFailure)(NSURLSessionDataTask *task, id responseObject, NSDictionary* requestParams);
/**
请求错误回调
*/
typedef void (^ReplyError)(NSError *error, NSURLSessionDataTask *task, NSDictionary* requestParams);
/* 上传进度
*
* @param bytesWritten 已上传的大小
* @param totalBytesWritten 总上传大小
*/
typedef void (^ReplyUploadProgress)(int64_t bytesWritten,int64_t totalBytesWritten);
typedef void (^MultipartData)(id formData);
/**
基础网络请求 其他的请求统一由此类发出
- HTTP_REQUEST_METHOD_GET:
- HTTP_REQUEST_METHOD_HEAD:
- HTTP_REQUEST_METHOD_POST:
- HTTP_REQUEST_METHOD_PUT:
- HTTP_REQUEST_METHOD_PATCH:
- HTTP_REQUEST_METHOD_DELETE:
*/
typedef NS_ENUM(NSUInteger, HTTP_REQUEST_METHOD) {
HTTP_REQUEST_METHOD_GET = 0,
HTTP_REQUEST_METHOD_HEAD,
HTTP_REQUEST_METHOD_POST,
HTTP_REQUEST_METHOD_PUT,
HTTP_REQUEST_METHOD_PATCH,
HTTP_REQUEST_METHOD_DELETE,
};
/**
网络请求缓存处理
- NetworkCacheType_Never: 重不进行缓存处理
- NetworkCacheType_OnlyCache: 只进行缓存,但是不读取
- NetworkCacheType_CacheAndLoad: 进行缓存,并且请求数据时先进行加载缓存,本次请求数据,下次加载
*/
typedef NS_ENUM(NSUInteger, NetworkCacheType) {
NetworkCacheType_Never = 0,
NetworkCacheType_OnlyCache,
NetworkCacheType_CacheAndLoad,
};
@interface FrankNetworkManage : NSObject
/**
* 创建单例对象
*/
+(instancetype)shareManager;
/**
网络数据的缓存处理类型
*/
@property (nonatomic,assign)NetworkCacheType cacheType;
/**
* 判断请求时是否需要 hud
*/
@property (nonatomic, assign) BOOL isShowHUD;
/**
* 请求之前的准备,可直接调用本类对象的 prepare
*/
@property (nonatomic, copy) RequestPrepare prepare;
/**
* 一个网络请求返回后做清理。
*/
@property (nonatomic,copy) RequestFinally finally;
/**
* 网络请求返回成功
*/
@property (nonatomic, copy) ReplySucess sucess;
/**
* 失败
*/
@property (nonatomic, copy) ReplyFailure failure;
/**
* 请求出错
*/
@property (nonatomic, copy) ReplyError error;
/**
共外界调用配置 判断逻辑【根据服务器返回值进行配置,可以在 Appdelegate 中进行设置】
*
* @return YES 表示数据正确,NO 表示后台的错误提示,证明返回有误
*/
@property (nonatomic,copy) BOOL (^judgeResponseIsSuccess)(id responseSuccess);
/*
*
* 用于指定网络请求接口的基础url,如:
* http://www.baudu.com
* 通常在AppDelegate中启动时就设置一次就可以了。
如果接口有来源于多个服务器,可以调用更新
*
*
* @param baseUrl 网络接口的基础url
*/
+ (void)updateBaseUrl:(NSString *)baseUrl;
/*
* 对外公开可获取当前所设置的网络接口基础url
*
* @return 当前基础url
*/
+ (NSString *)baseUrl;
/**
进行编码
*/
+ (NSString *)encodeUrl:(NSString *)url;
/**
自动判断 baseurl 并进行组合 url
*/
+ (NSString *)absoluteUrlWithPath:(NSString *)path;
/**
* 统一网络请求
*
* @param method 请求类型(直接调用 枚举)
* @param urlString 请求URLString
* @param headerParams 请求头添加的参数
* @param params 请求参数
* @param finally 请求结束,进行清理(直接调用)
* @param sucess 请求成功,数据正常
* @param failure 请求失败
* @param netError 请求连接错误
*/
+(void)httpRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method
urlString:(NSString *)urlString
headerParams:(NSDictionary *)headerParams
params:(id)params
finally:(RequestFinally) finally
sucess:(ReplySucess) sucess
failure:(ReplyFailure) failure
error:(ReplyError)netError;
/*
*
* 开启或关闭是否自动将URL使用UTF8编码,用于处理链接中有中文时无法请求的问题
*
* @param shouldAutoEncode YES or NO,默认为NO
*/
+ (void)shouldAutoEncodeUrl:(BOOL)shouldAutoEncode;
/*
* 图片上传接口,若不指定baseurl,可传完整的url
*
* @param image 图片对象
* @param url 上传图片的接口路径,如/path/images/
* @param filename 给图片起一个名字,默认为当前日期时间,格式为"yyyyMMddHHmmss",后缀为`jpg`
* @param name 与指定的图片相关联的名称,这是由后端写接口的人指定的,如imagefiles
* @param mimeType 默认为image/jpeg
* @param parameters 参数
* @param progress 上传进度
* @param success 上传成功回调
* @param fail 上传失败回调
*
* @return
*/
+ (void)uploadWithImage:(UIImage *)image
url:(NSString *)url
filename:(NSString *)filename
name:(NSString *)name
mimeType:(NSString *)mimeType
parameters:(NSDictionary *)parameters
progress:(ReplyUploadProgress)progress
success:(ReplySucess)success
fail:(ReplyError)fail;
/**
* 上传文件操作
*
* @param url 上传路径
* @param uploadingFile 待上传文件的路径
* @param progress 上传进度
* @param success 上传成功回调
* @param fail 上传失败回调
*
*/
+ (void)uploadFileWithUrl:(NSString *)url
uploadingFile:(NSString *)uploadingFile
progress:(ReplyUploadProgress)progress
success:(ReplySucess)success
fail:(ReplyError)fail;
其中需要注意的是@property (nonatomic,copy) BOOL (^judgeResponseIsSuccess)(id responseSuccess)
属性,这个是根据后台的数据格式配置请求结果判断的回调,只需要在AppDelegate
中进行配置一次就行。例如:
(2)网络下载框架:
#import "FrankNetworkManage.h"
/**
断点下载
- DownloadStatus_ResumingDown: 开始下载
- DownloadStatus_SuspendDown: 暂停下载
*/
typedef NS_ENUM(NSInteger ,DownloadStatus) {
DownloadStatus_ResumingDown = 0,
DownloadStatus_SuspendDown = 1,
};
@interface FrankHttpDownloadManage : FrankNetworkManage
/** AFNetworking断点下载(支持离线)需用到的属性 **********/
/**
文件的总长度
*/
@property (nonatomic,assign,readonly) NSInteger fileLength;
/**
当前下载长度
*/
@property (nonatomic,assign,readonly) NSInteger currentLength;
/**
下载文件保存路径
*/
@property (nonatomic,copy,readonly)NSString * downSavePath;
/**
* 下载文件操作
*
* @param url 下载地址
* @param saveName 保存文件名字
* @param progressBlock 下载进度
* @param success 下载成功回调
* @param failure 下载失败回调
*/
- (instancetype)initWithDownloadUrl:(NSString *)url
saveName:(NSString *)saveName
progress:(ReplyUploadProgress)progressBlock
success:(ReplySucess)success
failure:(ReplyError)failure;
/**
下载状态
- DownloadStatus_SuspendDown: 暂停下载
- DownloadStatus_ResumingDown: 开始下载
*/
-(void)setDownloadStatus:(DownloadStatus)status;
@end
(3)请求类BaseModel类 :
这个类是为了方便使用,而创建的一个基类框架,相当于在
ViewController
和FrankNetworkManage
中间添加的一层,用于处理数据交互相关逻辑,所以后期创建具体请求类只需要集成该BaseRequestHttpModel
类,重写父类方法即可。代码解析:
#import
#import "FrankNetworkMacro.h"
/**
请求成功时返回的数据
@param models 数据模型
*/
typedef void(^SuccessModel)(id models);
/**
代理方式下的 网络请求结果状态
- ResponseHttpType_Success: 请求成功
- ResponseHttpType_Failure: 请求失败
- ResponseHttpType_NetworkError: 网络异常
*/
typedef NS_ENUM(NSInteger,ResponseHttpType) {
ResponseHttpType_Success,
ResponseHttpType_Failure,
ResponseHttpType_NetworkError,
};
/**
代理方式下的 网络请求类型,枚举回调区分
*/
typedef NS_ENUM(NSInteger,BusinessHttpType) {
BusinessHttpType_None = 0,// 默认状态
BusinessHttpType_LoadWeather ,// 请求天气
// 此处可以根据自己的工程需求进行添加枚举分类。。。
};
#pragma mark -------- 通过 代理 方式处理请求回调,当使用 block 方式处理时,可以忽略代理 ---------
@protocol BaseRequestHttpModelDelegate
@optional
/**
* 为了降低耦合性,通过这个协议方法可以在对请求状态进行判断
*
* @param type 判断是哪一类发送的请求
* @param retStatus 请求成功失败的状态
*/
- (void)DoneBusiness:(enum BusinessHttpType)type status:(ResponseHttpType)retStatus;
@end
@interface BaseRequestHttpModel : NSObject
/**
请求地址
*/
@property (nonatomic,strong)NSString * urlStr;
/**
请求头数据字典
*/
@property (nonatomic,strong)NSMutableDictionary * headerParams;
/**
网络请求失败回调
*/
@property (nonatomic,copy)ReplyFailure failureBlock;
/**
网络错误回调
*/
@property (nonatomic,copy)ReplyError networkerrBlock;
#pragma mark -------- 通过 代理 方式处理请求回调 ---------
#pragma mark -------- 通过 代理 方式处理请求回调 ---------
/**
设置网络请求代理【当使用 block 方式处理时,可以忽略代理】
*/
@property (nonatomic,weak)id delegate;
/**
网络请求API类型
*/
@property (nonatomic,assign) BusinessHttpType businessType;
/**
告知当前网络处理状态
*/
-(void)doneBusiness:(ResponseHttpType)returnStatus;
/**
供子类调用 【 代理方式请求调用方法 】
@param method 请求方式
@param params 请求参数数据
@param isNeedHeader 是否需要 请求头数据
*/
-(void)doRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method
params:(id)params
isNeedHeaderParams:(BOOL)isNeedHeader;
#pragma mark -------- 通过 block 方式处理请求回调 ---------
#pragma mark -------- 通过 block 方式处理请求回调 ---------
/**
供子类调用 【 代理方式请求调用方法 】
@param method 请求方式
@param params 请求参数数据
@param isNeedHeader 是否需要 请求头数据
@param success 成功回调数据模型
@param fail 失败回调
@param errorBlock 链接错误回调
*/
-(void)doRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method
params:(id)params
isNeedHeaderParams:(BOOL)isNeedHeader
success:(SuccessModel)success
failure:(ReplyFailure)fail
netError:(ReplyError)errorBlock;
#pragma mark -------- 根据自己的需求进行重写,数据转模型 ---------
/**
之类需要根据自己的需求进行重写
处理请求成功时,字典转模型的具体实现,并返回字典模型
@param responseObject 响应数据
@param requestParams 请求数据
*/
-(id)changeDateForModelWithResponseObject:(id)responseObject requestParams:(NSDictionary *)requestParams;
@end
注意点:
(1)当使用代理方式进行处理网络回调时,需要设置
delegate
,调用请求方法
/**
供子类调用 【 代理方式请求调用方法 】
@param method 请求方式
@param params 请求参数数据
@param isNeedHeader 是否需要 请求头数据
*/
-(void)doRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method
params:(id)params
isNeedHeaderParams:(BOOL)isNeedHeader;
并且实现代理方法即可,后续的处理逻辑可以统一放在代理方法中进行处理
/**
* 为了降低耦合性,通过这个协议方法可以在对请求状态进行判断
*
* @param type 判断是哪一类发送的请求
* @param retStatus 请求成功失败的状态
*/
- (void)DoneBusiness:(enum BusinessHttpType)type status:(ResponseHttpType)retStatus
(2)当使用block
回调进行处理网络回调时,只需要调用请求方法,对于每一个请求结果的处理都可以单独进行处理
/**
供子类调用 【 代理方式请求调用方法 】
@param method 请求方式
@param params 请求参数数据
@param isNeedHeader 是否需要 请求头数据
@param success 成功回调数据模型
@param fail 失败回调
@param errorBlock 链接错误回调
*/
-(void)doRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method
params:(id)params
isNeedHeaderParams:(BOOL)isNeedHeader
success:(SuccessModel)success
failure:(ReplyFailure)fail
netError:(ReplyError)errorBlock;
但是不管是用那种方式,如果想要实现字典转模型,那都需要在子类中重写实现具体方法逻辑
/**
之类需要根据自己的需求进行重写
处理请求成功时,字典转模型的具体实现,并返回字典模型
@param responseObject 响应数据
@param requestParams 请求数据
*/
-(id)changeDateForModelWithResponseObject:(id)responseObject requestParams:(NSDictionary *)requestParams;
两种方式虽然方式不同,但是效果相同,所以只需要根据自己的喜好及业务需求进行选择使用即可。
(4)加载动画HUD展示:
这部分是加载动画hud,具体内容可移步 FrankActivityHUD 动画 进行查看
(5)设备信息加载工具 DeviceManager
:
这部分主要是为了方便查看、获取一些设备信息而集成的一个工具单例类,功能如下:
#import
#import
#import
//获取当前设备对应的height
#define Screen_height (MAX([[UIScreen mainScreen] bounds].size.height, [[UIScreen mainScreen] bounds].size.width))
//获取当前设备对应的width
#define Screen_width (MIN([[UIScreen mainScreen] bounds].size.height, [[UIScreen mainScreen] bounds].size.width))
//用于判断设备是否为长屏幕iphone,比如iphone5,iphone6,iphone6plus
#define IS_4inchIPHONE ( !IS_IPHONE4 )
//用于判断设备是否为iphone4
#define IS_IPHONE4 ( fabs( ( double )Screen_height - ( double )480 ) < DBL_EPSILON )
//用于判断设备是否为iphone5
#define IS_IPHONE5s_SE ( fabs( ( double )Screen_height - ( double )568 ) < DBL_EPSILON )
//用于判断设备是否为iphone6\iphone6plus
#define IS_IPHONE6_7 ( fabs( ( double )Screen_height - ( double )667 ) < DBL_EPSILON )
//用于判断设备是否为iphone6plus
#define IS_IPHONE6_PLUS ( fabs( ( double )Screen_height - ( double )736 ) < DBL_EPSILON)
//用于判断设备是否为iphone6之后
#define IS_IPHONE6_OR_LATER (((double)Screen_height - (double )568) > DBL_EPSILON)
// 比当前版本大
#define NOT_LESS_THAN_IOSVERSION(version) ([[[UIDevice currentDevice] systemVersion] floatValue] >= version)
// ios7 之后
#define IOS7_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending)
// ios8 之后
#define IOS8_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"8.0" options:NSNumericSearch] != NSOrderedAscending)
// ios9 之后
#define IOS9_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"9.0" options:NSNumericSearch] != NSOrderedAscending)
// ios10 之后
#define IOS10_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"10.0" options:NSNumericSearch] != NSOrderedAscending)
@interface DeviceManage : NSObject
/**
* 网络状态
*/
@property(nonatomic,copy)NSString * netWorkStatus;
/**
* 设备系统版本
*/
@property (nonatomic, copy) NSString *systemVersion;
/**
* 设备系统名
*/
@property (nonatomic, copy) NSString *systemName;
/**
* 机型
*/
@property (nonatomic, copy) NSString *deviceModel;
/**
* 设备名称(别名)
*/
@property (nonatomic, copy) NSString *deviceName;
/**
* 设备型号
*/
@property (nonatomic, copy) NSString *deviceType;
/**
* 手机总存储容量
*/
@property (nonatomic, strong)NSString * totalDSB;
/**
* 手机空闲存储容量
*/
@property (nonatomic, strong)NSString * freeDSB;
/**
* 手机总内存容量
*/
@property (nonatomic, strong)NSString * totalMB;
/**
* 手机空闲内存容量
*/
@property (nonatomic, strong)NSString * freeMB;
/**
* cpu类型
*/
@property(nonatomic,strong)NSString * cpuType;
/**
* 屏幕宽度
*/
@property (nonatomic, assign) CGFloat screenWidth;
/**
* 屏幕高度
*/
@property (nonatomic, assign) CGFloat screenHeight;
/**
* 分辨率
*/
@property (nonatomic, assign) CGFloat screenScale;
/**
* 处理器(多核)
*/
@property (nonatomic, assign) NSInteger cpuCoreCount;
/**
* 应用版本 【version】
*/
@property (nonatomic, strong) NSString *applicationMajorVersion;
/**
* 最小版本 【build version】
*/
@property (nonatomic, strong) NSString *applicationMinorVersion;
/**
* 当前应用名
*/
@property (nonatomic, strong) NSString *applicationDisplayName;
/**
* 应用标识符
*/
@property (nonatomic, strong) NSString *applicationIdentifier;
/**
* 启动状态
*/
@property (nonatomic, assign) NSInteger fetchLocationErrorCode;//-2--not started or OK, -1--in progress, >=0----failed
/**
* 获取手机 IP 地址
*/
@property (nonatomic, strong) NSString * phoneIPAdress;
/**
* 获取手机 Mac 地址
*/
@property (nonatomic, strong) NSString * phoneMacAddress;
/**
* 获取单例对象
*/
+(DeviceManage *)shareDeviceManage;
@end
(6)数据库存储框架:
文件中包含三个类文件:
(1)FrankFMDBManage:
是基于FMDB
集成的数据库工具,隔离了SQL语句
繁琐的操作,并且结合runtime
实现了对象的直接存储操作,支持增、删、改、查、支持原始网络数据的存储(2)FrankUserDefaults:
是对 NSUserDefaults
进行的一个简单封装,并且提供了不同类型数据的本地读写功能(3)NSString+Category:
是对NSString
的一个分类,将一些常用的NSString
功能方法进行封装,以便调用
具体的使用详情可参见 Demo链接: https://github.com/Kinglions/FrankNetworkManage 如有发现存在问题,希望可以及时提出,相互交流,共同进步