我们其实在写大型程序的时候最好不要直接让大型的框架直接进入项目中,因为这样耦合性会很强,你的程序就离不开AFN了,这样的情况肯定不是我们希望的,比如说AFN如果有重大的更新,我们如果用的是直接引入框架的方法,那我们需要改的东西有很多,如果我们通过封装一个工具类,来进行网络请求,这样的话,耦合性降低,实现的效果也是一样的。我们怎么进行封装,我们其实可以先去看AFN中内部的源代码是怎么实现的,AFN内部发送GET请求和POST请求都是通过dataTaskWithHTTPMethod,这个方法来实现的,所以我们也可以通过这个方法来定义我们封装的方法,首先先附上.h文件的代码
#import <AFNetworking/AFNetworking.h>
//ZXRequestMethod相当于表示一个数据类型
typedef enum : NSInteger {
GET,
POST,
} ZXRequestMethod;
@interface NetworkTools : AFHTTPSessionManager
+(instancetype)sharedTools;
-(void)request:(ZXRequestMethod)method URLString:(NSString *)URLString parameters:(id)parameters progress:(CGFloat)progress finished:(void(^)
(id, NSError *))finished;
@end
.m文件中的代码#import "NetworkTools.h"
//定义网络工具协议,可以去获取到AFN内部发GET和POST请求实现的方法
@protocol NetworkToolsDelegate <NSObject>
@optional
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
success:(void (^)(NSURLSessionDataTask *, id))success
failure:(void (^)(NSURLSessionDataTask *, NSError *))failure;
@end
//遵守这个协议就是为了让Xcode给一个智能提示,因为dataTaskWithHTTPMethod这个方法是AFN中私有的,我们遵守了这个协议就可以敲出这个方法,也就可以使用了
@interface NetworkTools()<NetworkToolsDelegate>
@end
@implementation NetworkTools
+(instancetype)sharedTools
{
static NetworkTools * tools;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//基本的URL地址,末尾需要有斜杠,之后调用参数就可以了
NSURL * baseURL = [NSURL URLWithString:@"http://httpbin.org/"];
tools = [[self alloc]initWithBaseURL:baseURL];
tools.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", nil];
});
return tools;
}
-(void)request:(ZXRequestMethod)method URLString:(NSString *)URLString parameters:(id)parameters progress:(CGFloat)progress finished:(void(^)(id, NSError *))finished
{
NSString * methodName = (method == GET) ? @"GET" : @"POST";
//虽然本类中没有实现这个方法,但是父类是实现了的,所以我们在调用这个方法的时候,如果本类中没有提供,会直接的去调用父类的方法,因为AFN中内部已经实现了
[[self dataTaskWithHTTPMethod:methodName URLString:URLString parameters:parameters uploadProgress:^(NSProgress *uploadProgress) {
} downloadProgress:^(NSProgress *downloadProgress) {
CGFloat progress = downloadProgress.completedUnitCount *1.0 / downloadProgress.totalUnitCount;
NSLog(@"%f",progress);
} success:^(NSURLSessionDataTask *task, id responseObject) {
finished(responseObject,nil);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
finished(nil,error);
}]resume];
}
@end
在OC中是以消息发送的机制来传递的,所以我们可以这么做,但如果是Swift就不可以这么做了。