随着ipv6的使用,AFNetWoring发布了3.0版本,刚刚完成的这个项目我用的是AF3.0,这里有这次使用AF3.0的封装,简单说一下都是怎么做的。
1.单例形式创建AFHTTPSessionManager的子类。
+ (instancetype)sharedClient {
static AFAppDotNetAPIClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[AFAppDotNetAPIClient alloc] initWithBaseURL:[NSURL URLWithString:AFAppDotNetAPIBaseURLString]];
_sharedClient.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",nil];
_sharedClient.requestSerializer.timeoutInterval = 30; // 设置超时时间30s
//支持https,SSL证书加密
// AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
// securityPolicy.allowInvalidCertificates = YES;
// securityPolicy.validatesDomainName = NO;
// _sharedClient.securityPolicy = securityPolicy;
});
return _sharedClient;
}
2.封装基本通用的请求方法
.h接口文件
/**
* 返回json结构为CommenReturnModel的HTTP请求
*
* @param parameters 参数集,为#NSDictionary#类型
* @param POST 地址,除BaseUrl之外的部分
* @param block block参数
*
* @return 返回值
*/
+(NSURLSessionDataTask*)normalHttpRequestWithParameters:(NSDictionary*)parameters POST:(NSString*)POST resultBlock:(void(^)(NSDictionary* commentReturnModel, NSError*error))block;
/*!
* 上传图片接口
*
* @param parameters 参数集,为#NSDictionary#类型
* @param picDic 图片字典{key为推荐命名。value为图片}
* @param POST 地址,除BaseUrl之外的部分
* @param block block参数
*
* @return 返回值
*/
+(NSURLSessionDataTask*)uploadHttpRequestWithParameters:(NSDictionary*)parameters PictureDic:(NSDictionary *)picDic POST:(NSString*)POST resultBlock:(void(^)(NSDictionary* commentReturnModel, NSError*error))block;
.m实现文件
//返回json结构为CommenReturnModel的HTTP请求
+(NSURLSessionDataTask*)normalHttpRequestWithParameters:(NSDictionary *)parameters POST:(NSString *)POST resultBlock:(void (^)(NSDictionary *, NSError *))block{
DEBUGLog(@"%@%@?%@",AFAppDotNetAPIBaseURLString, POST, [self getStringWithDictionary:parameters]);
dispatch_async(dispatch_get_main_queue(), ^{
[[MbprogressTool standard] showprogressHUD];
});
NSString * post = [NSString stringWithFormat:@"%@%@",AFAppDotNetAPIBaseURLString,POST];
return [[AFAppDotNetAPIClient sharedClient] POST:post parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
DEBUGLog(@"%@",responseObject);
NSAssert([responseObject isKindOfClass:[NSDictionary class]], @"JSON结构返回与约定不符");
if (block) {
block(responseObject, nil);
}
[[MbprogressTool standard] hiddenProgressHUD];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (block) {
block(nil, error);
}
[[MbprogressTool standard] hiddenProgressHUD];
}];
}
//图片上传
+(NSURLSessionDataTask *)uploadHttpRequestWithParameters:(NSDictionary *)parameters PictureDic:(NSDictionary *)picDic POST:(NSString *)POST resultBlock:(void (^)(NSDictionary *, NSError *))block{
NSString * post = [NSString stringWithFormat:@"%@%@",AFAppDotNetAPIBaseURLString,POST];
dispatch_async(dispatch_get_main_queue(), ^{
[[MbprogressTool standard] showprogressHUD];
});
return [[AFAppDotNetAPIClient sharedClient] POST:post parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
for (NSString *keyString in [picDic allKeys]){
NSData *imgData = [picDic objectForKey:keyString];
if (imgData.length > 0) {
[formData appendPartWithFileData:imgData name:keyString fileName:[NSString stringWithFormat:@"%@%u.jpg", keyString,arc4random()%98] mimeType:@"image/jpeg"];
DEBUGLog(@"图片上传%@",keyString);
}
}
} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
DEBUGLog(@"%@",parameters);
NSAssert([responseObject isKindOfClass:[NSDictionary class]], @"JSON结构返回与约定不符");
if (block) {
block(responseObject, nil);
}
[[MbprogressTool standard] hiddenProgressHUD];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (block) {
block(nil, error);
}
[[MbprogressTool standard] hiddenProgressHUD];
}];
}
3.具体接口再次对通用接口进行封装(嫌麻烦的话直接用通用的也可以)
我这里是用对上面的通用接口类加不同的扩展实现的(下图也是我的整个网络部分结构)
一个具体的实现例子
/*!
* 查询收藏列表
*
* @param currectPage 当前页面
* @param block block description
*
* @return return value description
*/
+(NSURLSessionDataTask*)getMyCollectListIsCurretPage:(NSInteger)currectPage ResultBlock:(void(^)(NSArray * model, NSString *failMessage))block;
+(NSURLSessionDataTask*) getMyCollectListIsCurretPage:(NSInteger)currectPage ResultBlock:(void(^)(NSArray * model, NSString *failMessage))block{
NSDictionary * parma = @{@"userId":@"",
@"pageSize":@"10",
@"pageIndex":@(currectPage)};
return [self normalHttpRequestWithParameters:parma POST:isBaby?MyCollectBabyListURL:MyCollectShowListURL resultBlock:^(NSDictionary *commentReturnModel, NSError *error) {
if (!error){//成功是操作
if ([[commentReturnModel objectForKey:@"status"] integerValue] == DEF_SUCESS_CODE){
NSMutableArray * dataArr = [[NSMutableArray alloc]init];
[commentReturnModel[@"data"][@"dataList"] enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (isBaby) {
MyCollectBabyModel * styleModel = [[MyCollectBabyModel alloc]initWithDictionary:obj];
[dataArr addObject:styleModel];
}else{
MyCollectShowBabyModel * styleModel = [[MyCollectShowBabyModel alloc]initWithDictionary:obj];
[dataArr addObject:styleModel];
}
}];
NSArray * model = [NSArray arrayWithArray:dataArr];
if (block) {
block(model, nil);
}
}
else{//失败时的操作
if (block) {
block(nil, [commentReturnModel objectForKey:@"msg"]);
}
}
}else{//错误时的操作
if (block) {
block(nil, @"网络请求失败");
}
}
}];
}
上面就是我的AF的封装其中还有两个类说一下
1.NetRequestUrls 这里我是存放了所有的接口地址,这样方便统一管理,
2.MbprogressTool则是对于MB的一个封装
在上面通用方法的时候大家应该发现了我在开始请求的时候调用了一下,在结束是停止,这样就可以买一个请求都有MB了不用在所有地方都写。MbprogressTool具体实现如下:
.h接口文件
#import <Foundation/Foundation.h>
@interface MbprogressTool : NSObject
+(instancetype)standard;
-(void)showprogressHUD;
-(void)hiddenProgressHUD;
-(UIViewController *)getCurrentVC;
@end
.m实现文件
#import "MbprogressTool.h"
#import <MBProgressHUD.h>
#import <UIImage+GIF.h>
@interface MbprogressTool ()
@property (nonatomic, strong) MBProgressHUD *progressHUD;
@property (nonatomic, assign) NSInteger referenceCount;//引用mb的个数
@end
@implementation MbprogressTool
+(instancetype)standard{
static MbprogressTool *mbprogressTool = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mbprogressTool = [[MbprogressTool alloc] init];
mbprogressTool.progressHUD = [[MBProgressHUD alloc]init];
mbprogressTool.progressHUD.color = [UIColor clearColor];
mbprogressTool.progressHUD.mode = MBProgressHUDModeCustomView;
UIImageView * imageView = [[UIImageView alloc]initWithImage:[UIImage sd_animatedGIFNamed:@"刷新gif"]];
imageView.layer.cornerRadius = 15;
imageView.layer.masksToBounds = YES;
imageView.alpha = 0.7;
imageView.frame = CGRectMake(0, 0, 123/1.5, 123/1.5);
mbprogressTool.progressHUD.customView = imageView;
mbprogressTool.progressHUD.removeFromSuperViewOnHide = YES;
//mbprogressTool.progressHUD.labelText=@"加载中...";
//mbprogressTool.progressHUD.labelFont = DEF_STFont(14.0);
mbprogressTool.referenceCount = 0;
});
return mbprogressTool;
}
-(void)showprogressHUD{
_referenceCount++;
if ([self getCurrentVC].navigationController != nil) {
[[self getCurrentVC].navigationController.view addSubview:_progressHUD];
}else{
[[self getCurrentVC].view addSubview:_progressHUD];
}
[_progressHUD show:YES];
}
-(void)hiddenProgressHUD{
_referenceCount--;
if (_referenceCount == 0) {
[_progressHUD hide:YES];
}
// [_progressHUD removeFromSuperview];
}
//获取当前屏幕显示的viewcontroller
-(UIViewController *)getCurrentVC
{
UIViewController *result = nil;
UIWindow * window = [[UIApplication sharedApplication] keyWindow];
if (window.windowLevel != UIWindowLevelNormal){
NSArray *windows = [[UIApplication sharedApplication] windows];
for(UIWindow * tmpWin in windows){
if (tmpWin.windowLevel == UIWindowLevelNormal){
window = tmpWin;
break;
}
}
}
UIView *View = [[window subviews] objectAtIndex:0];
UIView *frontView = [[View subviews] lastObject];
id nextResponder = [frontView nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]){
result = nextResponder;
}
else{
result = window.rootViewController;
}
return result;
}
@end
写完了,因为现在完成的这个项目就是用的这套东西所以使用起来应该没有问题,有什么问题可以问我,,,