实际开发中直接拿AFN来用多少回有点不顺手,个人简单的封装了一下afn,包括get ,post,网络请求和上传下载(断点下载虽然实现了,但是总感觉有点小问题,后期会继续完善),另外请求的缓存这一块还没做,后期会继续完善的
更新:
2016.12.18
1.增加缓存功能,post,get都可以读取缓存(缓存这一块用的YYCache,由于YYCache效率高,所以集成了)
这里对 isReaderCache参数做下说明,YES为加载缓存,即在没网和请求出错的情况下都会去加载缓存,请求成功的情况下还是去加载后台返回的数据,NO默认不加载任何缓存,调试接口时设置为NO,这样可以看出错误原因,方便调试,本来想去请求成功判断是否去加载缓存的,但是这个要根据情况而定,需要和后台去沟通,所以暂时不去集成
2.增加HTTPS验证,由于之前公司APP撤掉不做了,服务器已经挂掉,所以无法验证,如果验证不成功,请删除相关验证的额代码
/**
get请求
@param url 请求url
@param params 参数
@param isReadCache 是否读取缓存
@param success 成功回调
@param failed 失败回调
*/
+ (void)getWithUrl: (NSString *)url params: (NSDictionary *)params isReadCache: (BOOL)isReadCache success: (responseSuccess)success failed: (responseFailed)failed;
步骤:
1.创建管理者单例,方便统一管理
//单例
+ (instancetype)sharedManager {
static dispatch_once_t onceToken;
static JZLNetworkingTool *instance;
dispatch_once(&onceToken, ^{
NSURL *baseUrl = [NSURL URLWithString:@""];
instance = [[JZLNetworkingTool alloc] initWithBaseURL:baseUrl];
instance.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json",
@"text/html",
@"text/json",
@"text/plain",
@"text/javascript",
@"text/xml",
@"image/*"]];
});
return instance;
}
2.简单的对请求返回成功和失败,以及进度回调的block
//请求成功的回调block
typedef void(^responseSuccess)(NSURLSessionDataTask *task, id responseObject);
//请求失败的回调block
typedef void(^responseFailed)(NSURLSessionDataTask *task, NSError *error);
//文件下载的成功回调block
typedef void(^downloadSuccess)(NSURLResponse *response, NSURL *filePath);
//文件下载的失败回调block
typedef void(^downloadFailed)( NSError *error);
//文件上传下载的进度block
typedef void (^progress)(NSProgress *progress);
3.get请求的封装
/**
get请求
@param url 请求url
@param params 参数
@param success 成功回调
@param failed 失败回调
*/
+ (void)getWithUrl: (NSString *)url params: (NSDictionary *)params success: (responseSuccess)success failed: (responseFailed)failed ;
//实现
//get请求
+ (void)getWithUrl: (NSString *)url params: (NSDictionary *)params success: (responseSuccess)success failed: (responseFailed)failed {
[[JZLNetworkingTool sharedManager] GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//请求成功的回调
if (success) {
success(task,responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//请求失败的回调
if (failed) {
failed(task,error);
}
}];
}
4.post请求的封装
/**
post请求
@param url 请求url
@param params 参数
@param success 成功回调
@param failed 失败回调
*/
+ (void)postWithUrl: (NSString *)url params: (NSDictionary *)params success: (responseSuccess)success failed: (responseFailed)failed ;
//实现
//post请求
+ (void)postWithUrl:(NSString *)url params:(NSDictionary *)params success:(responseSuccess)success failed:(responseFailed)failed {
[[JZLNetworkingTool sharedManager] POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(task,responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failed) {
failed(task,error);
}
}];
}
5.上传的实现
/**
文件上传(图片上传)
@param url 请求url
@param params 请求参数
@param fileData 上传文件的二进制数据
@param name 制定参数名
@param fileName 文件名(加后缀名)
@param mimeType 文件类型
@param progress 上传进度
@param success 成功回调
@param failed 失败回调
*/
+ (void)uploadWithUrl: (NSString *)url params: (NSDictionary *)params fileData: (NSData *)fileData name: (NSString *)name fileName: (NSString *)fileName mimeType: (NSString *)mimeType progress: (progress)progress success: (responseSuccess)success failed: (responseFailed)failed;
//实现
//文件上传
+ (void)uploadWithUrl: (NSString *)url params: (NSDictionary *)params fileData: (NSData *)fileData name: (NSString *)name fileName: (NSString *)fileName mimeType: (NSString *)mimeType progress: (progress)progress success: (responseSuccess)success failed: (responseFailed)failed {
[[JZLNetworkingTool sharedManager] POST:url parameters:params constructingBodyWithBlock:^(id _Nonnull formData) {
[formData appendPartWithFileData:fileData name:name fileName:fileName mimeType:mimeType];
} progress:^(NSProgress * _Nonnull uploadProgress) {
if (progress) {
progress(uploadProgress);
}
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(task,responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failed) {
failed(task,error);
}
}];
}
6.下载的实现,一开始下载实现
一开始我使用下面这个API去实现下载,但是断点下载遇到了问题,一直开在断点下载这一块,所以后来取消了,这个只能实现下载,但是断点下载不可以(头文件中已经删除了这个方法)(有大神实现了可以分享学习下)
//文件下载
+ (void)downloadWithUrl: (NSString *)url savePathUrl: (NSURL *)fileUrl progress: (progress)progress success: (downloadSuccess)success failed: (downloadFailed)failed {
NSURL *urlPath = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:urlPath];
NSURLSessionDownloadTask *downloadTask = [[JZLNetworkingTool sharedManager] downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
//可以在此block里面返回主线程去刷新下载进度条
progress(downloadProgress);
if (downloadProgress.totalUnitCount == 1) {
//下载完成清空断点数据
[JZLNetworkingTool sharedManager].resumeData = nil;
//清除沙盒文件
NSFileManager *fileMger = [NSFileManager defaultManager];
NSString *resumePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:[JZLNetworkingTool sharedManager].resumeDataPath];
if ([fileMger fileExistsAtPath:resumePath]) {
NSError *err;
[fileMger removeItemAtPath:resumePath error:&err];
}
}
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
return [fileUrl URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
if (error) {
failed(error);
}else {
//可以根据文件路径拿到下载的文件进行操作,比如显示图片
success(response,filePath);
[JZLNetworkingTool sharedManager].dataPath = [filePath absoluteString];
}
}];
[JZLNetworkingTool sharedManager].downloadTask = downloadTask;
[downloadTask resume];
}
后来又重新整理了下,实现了断点下载,测试成功,不知道实际还会不会有问题,有问题会继续修改
1.自定义session,设置代理
- (NSURLSession *)downloadSession
{
if (_downloadSession == nil) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
// nil : nil的效果跟 [[NSOperationQueue alloc] init] 是一样的
_downloadSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
}
return _downloadSession;
}
2/下载
//文件下载 支持断点下载
+ (void)downloadWithUrl: (NSString *)url {
// 1. URL
NSURL *URL = [NSURL URLWithString:url];
// 2. 发起下载任务
[JZLNetworkingTool sharedManager].downloadTask = [[JZLNetworkingTool sharedManager].downloadSession downloadTaskWithURL:URL];
// 3. 启动下载任务
[[JZLNetworkingTool sharedManager].downloadTask resume];
}
3.暂停下载
//暂停下载
- (void)pauseDownload {
[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
self.resumeData = resumeData;
//将已经下载的数据存到沙盒,下次APP重启后也可以继续下载
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 拼接文件路径 上面获取的文件路径加上文件名
NSString *path = [@"sssssaad" stringByAppendingString:@".plist"];
NSString *plistPath = [doc stringByAppendingPathComponent:path];
self.resumeDataPath = plistPath;
[resumeData writeToFile:plistPath atomically:YES];
self.resumeData = resumeData;
self.downloadTask = nil;
}];
}
4.继续下载
//继续下载
- (void)resumeDownloadprogress: (progress)progress success: (downloadSuccess)success failed: (downloadFailed)failed {
if (self.resumeData == nil) {
NSData *resume_data = [NSData dataWithContentsOfFile:self.resumeDataPath];
if (resume_data == nil) {
// 即没有内存续传数据,也没有沙盒续传数据,就续传了
return;
} else {
// 当沙盒有续传数据时,在内存中保存一份
self.resumeData = resume_data;
}
}
// 续传数据时,依然不能使用回调
// 续传数据时起始新发起了一个下载任务,因为cancel方法是把之前的下载任务干掉了 (类似于NSURLConnection的cancel)
// resumeData : 当新建续传数据时,resumeData不能为空,一旦为空,就崩溃
// downloadTaskWithResumeData :已经把Range封装进去了
if (self.resumeData != nil) {
self.downloadTask = [self.downloadSession downloadTaskWithResumeData:self.resumeData];
// 重新发起续传任务时,也要手动的启动任务
[self.downloadTask resume];
}
}
5.实现下面的两个代理方法,一个是监听下载进度.另外一个是文件下载结束的代理方法(必须实现)
/// 监听文件下载进度的代理方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
// 计算进度
float downloadProgress = (float)totalBytesWritten / totalBytesExpectedToWrite;
NSLog(@"%f",downloadProgress);
}
/// 文件下载结束时的代理方法 (必须实现的)
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
// location : 文件下载结束之后的缓存路径
// 使用session实现文件下载时,文件下载结束之后,默认会删除,所以文件下载结束之后,需要我们手动的保存一份
NSLog(@"%@",location.path);
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
// NSString *path = @"/Users/allenjzl/Desktop/ssssss/zzzz.zip";
// 文件下载结束之后,需要立即把文件拷贝到一个不会销毁的地方
[[NSFileManager defaultManager] copyItemAtPath:location.path toPath:[path stringByAppendingString:@"/.zzzzzzz.zip"] error:NULL];
NSLog(@"%@",path);
}
直接拖JZLNetworkingTool两个头文件到项目就可以使用
因为自己工作的项目遇到电商的很多,数据缓存这一块很重要,之前都是用的别人封装好的,接下来会继续完善这个请求,缓存这一块加进去,还有网络监测这一块,未完待续......
如果能帮到你,我很高兴,请star一下下,如果你发现问题,请指出来,共同进步
demo github地址: https://github.com/allenjzl/JZLNetworking.git