网络请求之基于AFN的二次封装从AFN1.0升级到3.0后)

本文介绍了基于AFNetworking的网络请求封装方法,包括针对不同版本的AFNetworking进行了详细的封装示例,涉及POST和GET请求,并展示了如何使用调度组来并发执行多个网络请求。

第一部分,基于AFN3.0进行二次封装,法相3.0的请求速度要高于1.0的。其中多个接口异步发起请求主要是用到了调度组。

自行使用pod去集成AFN.如果不会的可以去网上查看资料,太多了,就不再赘述了,直接上代码。

#import <UIKit/UIKit.h>
@class AFHTTPRequestOperation;
@interface HTTPTool : NSObject


/**
 *  这是一个post请求,用来返回json数据的
 *
 *  @param serverAddress 服务器域名,如果为空取默认的地址
 *  @param portAddress 端口号
 *  @param parameters    请求参数
 *  @param success  成功回调
 *  @param failure  失败回调
 */
+ (void)HTTP_POSTWithServerAddress:(NSString *)serverAddress
                       portAddress:(NSString *)portAddress
                        parameters:(NSMutableDictionary *)parameters
                           success:(void (^)(id jsonObject))success
                           failure:(void (^)(NSError *error))failure;


/**
 *  这是一个get请求,用来返回json数据的
 *
 *  @param serverAddress 服务器域名,如果为空取默认的地址
 *  @param portAddress 端口号
 *  @param parameters    请求参数
 *  @param success  成功回调
 *  @param failure  失败回调
 */
+ (void)HTTP_GETWithServerAddress:(NSString *)serverAddress
                      portAddress:(NSString *)portAddress
                       parameters:(NSMutableDictionary *)parameters
                          success:(void (^)(id jsonObject))success
                          failure:(void (^)(NSError *error))failure;

/**
 这个方法是用来多个接口同时发起网络请求的,这个方法完全可以不要,但是考虑到之前项目的代码逻辑还是保留了下来,
 
 @param method @"POST"/@"GET"
 @param serverAddress 服务器地址
 @param portAddress 端口号
 @param parameters 参数
 @param success 成功回调
 @param failure 失败回调
 
 使用方法如下, dispatch_group_t group = dispatch_group_create();
 dispatch_group_enter(group);
 [HTTPTool HTTP_Method:@"POST" serverAddress:nil portAddress:@"端口号" parameters:@"参数" success:^(id responseObject) {
 dispatch_group_leave(group);
 } failure:^(NSError *error) {
 dispatch_group_leave(group);
 }];
 dispatch_group_notify(group, dispatch_get_main_queue(), ^{
 //网络请求完成
 });
 
 */
+ (void )HTTP_Method:(NSString *)method
       serverAddress:(NSString *)serverAddress
         portAddress:(NSString *)portAddress
          parameters:(id)parameters
             success:(void (^)(id responseObject))success
             failure:(void (^)(NSError *error))failure;


@end

.m中实现

import "HTTPTool.h"
#import<CommonCrypto/CommonDigest.h>
#import "AFNetworking.h"
@implementation HTTPTool

static NSString *_operationSource = nil;
static NSString *_currentVersion = nil;
+  (void)initialize{
    _currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
    NSString* localPhoneModel = [[UIDevice currentDevice] localizedModel];
    _operationSource = [localPhoneModel isEqualToString:@"iPad"] ? @"ipad" : @"iphone";
}

+ (void )HTTP_Method:(NSString *)method serverAddress:(NSString *)serverAddress portAddress:(NSString *)portAddress parameters:(id)parameters success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure{
    if ([method isEqualToString:@"POST"] || [method isEqualToString:@"post"]) {
        [self HTTP_POSTWithServerAddress:nil portAddress:portAddress parameters:parameters success:^(id jsonObject) {
            success(jsonObject);
        } failure:^(NSError *error) {
            failure(error);
        }];
    }
    
    if ([method isEqualToString:@"GET"]|| [method isEqualToString:@"get"]) {
        [self HTTP_GETWithServerAddress:nil portAddress:portAddress parameters:parameters success:^(id jsonObject) {
            success(jsonObject);
        } failure:^(NSError *error) {
            failure(error);
        }];
    }
}

+ (void)HTTP_POSTWithServerAddress:(NSString *)serverAddress portAddress:(NSString *)portAddress parameters:(NSMutableDictionary *)parameters success:(void (^)(id))success failure:(void (^)(NSError *))failure{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = 10.0f;
    NSString *basaeUrl = nil;
    if (!serverAddress) {
        basaeUrl = [@"服务器地址" stringByAppendingPathComponent:portAddress];
    } else {
        basaeUrl = [serverAddress stringByAppendingPathComponent:portAddress];
    }
    
    [manager POST:basaeUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success(responseObject);
        //code
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@",error);
    }];
}


+ (void)HTTP_GETWithServerAddress:(NSString *)serverAddress portAddress:(NSString *)portAddress parameters:(NSMutableDictionary *)parameters success:(void (^)(id))success failure:(void (^)(NSError *))failure{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = 10.0f;
    NSString *baaseUrl = nil;
    if (!serverAddress) {
        baaseUrl = [@"服务器地址" stringByAppendingPathComponent:portAddress];
    } else {
        baaseUrl = [serverAddress stringByAppendingPathComponent:portAddress];
    }
    
    [manager GET:baaseUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success(responseObject);
        //code 跟后台约定的规则进行处理就可以了
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        failure(error);
    }];
}
@end

项目中如何使用:以同时发起两个请求为例,如果是一个接口,直接调用get/post方法即可,不用使用调度组。

#import "ViewController.h"
#import "HTTPTool.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    NSMutableDictionary *resumeDict = [NSMutableDictionary dictionary];
    [HTTPTool HTTP_Method:@"POST" serverAddress:nil portAddress:@"端口号1" parameters:resumeDict success:^(id responseObject) {
        dispatch_group_leave(group);
        NSLog(@"%@",responseObject);
    } failure:^(NSError *error) {
        dispatch_group_leave(group);
        NSLog(@"%@",error);
    }];
 
    dispatch_group_enter(group);
    [HTTPTool HTTP_Method:@"GET" serverAddress:@"新服务器地址" portAddress:@"端口号2" parameters:resumeDict success:^(id responseObject) {
        dispatch_group_leave(group);
        NSLog(@"%@",responseObject);
    } failure:^(NSError *error) {
        dispatch_group_leave(group);
        NSLog(@"%@",error);
    }];
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        //网络请求完成
        NSLog(@"wancheng");
    });
}

@end


第二部分:早期AFNetworking1.x版本的封装

#import <UIKit/UIKit.h>
@class AFHTTPRequestOperation;
@interface HTTPTool : NSObject


/**
 *  这是一个post请求,用来返回json数据的
 *
 *  @param serverAddress 服务器域名,如果为空取默认的地址
 *  @param portAddress 端口号
 *  @param parameters    请求参数
 *  @param success  成功回调
 *  @param failure  失败回调
 */
+ (void)HTTP_POSTWithServerAddress:(NSString *)serverAddress
                       portAddress:(NSString *)portAddress
                        parameters:(NSMutableDictionary *)parameters
                           success:(void (^)(id jsonObject))success
                           failure:(void (^)(NSError *error))failure;


/**
 *  这是一个get请求,用来返回json数据的
 *
 *  @param serverAddress 服务器域名,如果为空取默认的地址
 *  @param portAddress 端口号
 *  @param parameters    请求参数
 *  @param success  成功回调
 *  @param failure  失败回调
 */
+ (void)HTTP_GETWithServerAddress:(NSString *)serverAddress
                      portAddress:(NSString *)portAddress
                       parameters:(NSMutableDictionary *)parameters
                          success:(void (^)(id jsonObject))success
                          failure:(void (^)(NSError *error))failure;



/**
 *  这个方法不会主动去执行,需要添加到一个Queue中才能执行具体的业务
 *
 *  @param method     @"POST"\@"GET"
 *  @param serverAddress   服务器地址,如果为空取默认的地址
 *  @param portAddress   端口号
 *  @param parameters 传入的参数
 *  @param success    成功回调
 *  @param failure    失败回调
 *
 *  @return 这个方法需要手动添加到队列组中才能执行,一般情况需要结合下面的方法,将几个网络请求同时异步发送,然后在回调中completionBlock,刷新界面
 
 NSArray *operations = [AFHTTPRequestOperation batchOfRequestOperations:@[opreationOne, opreationTwo] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
 
 NSLog(@"%ld/%ld", numberOfFinishedOperations, totalNumberOfOperations);
 
 } completionBlock:^(NSArray *operations) { // 所有请求结束在这里加载数据
 
 NSLog(@"completionBlock");
 
 }];
 
 [[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO]; // NO不会阻塞主线程
 
 */
+ (AFHTTPRequestOperation *)HTTP_Method:(NSString *)method
                          serverAddress:(NSString *)serverAddress
                            portAddress:(NSString *)portAddress
                             parameters:(id)parameters
                                success:(void (^)(id responseObject))success
                                failure:(void (^)(NSError *error))failure;


@end

.m中如何实现

#import "HTTPTool.h"
#import "AFNetworking.h"
@implementation HTTPTool



+ (AFHTTPRequestOperation *)HTTP_Method:(NSString *)method serverAddress:(NSString *)serverAddress portAddress:(NSString *)portAddress parameters:(id)parameters success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure{
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = 10.0f;
    NSString *bsaeUrl = nil;
    if (!serverAddress) {
        
        bsaeUrl = [@"服务器地址" stringByAppendingPathComponent:portAddress];
    } else {
        bsaeUrl = [serverAddress stringByAppendingPathComponent:portAddress];
    }
    // 注:afn没有这个方法,是我同事自己在AFHTTPRequestOperationManager中添加的。实现原理如下
      /*- (AFHTTPRequestOperation *)HTTPRequestOperationWithHTTPMethod:(NSString *)method
            URLString:(NSString *)URLString
            parameters:(id)parameters
            success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
            failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
                {
                    NSError *serializationError = nil;
                    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
                    if (serializationError) {
                        if (failure) {
            #pragma clang diagnostic push
            #pragma clang diagnostic ignored "-Wgnu"
                            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                                failure(nil, serializationError);
                            });
            #pragma clang diagnostic pop
                        }
     
                        return nil;
                    }
     
                    return [self HTTPRequestOperationWithRequest:request success:success failure:failure];
      }*/
    
    
    AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithHTTPMethod:method URLString:bsaeUrl parameters:parameters success:^(AFHTTPRequestOperation * _Nonnull operation, id  _Nonnull responseObject) {
        success(responseObject);
    } failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) {
        failure(error);
    }];
    
    return operation;
}

+ (void)HTTP_POSTWithServerAddress:(NSString *)serverAddress portAddress:(NSString *)portAddress parameters:(NSMutableDictionary *)parameters success:(void (^)(id))success failure:(void (^)(NSError *))failure{
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = 10.0f;
    NSString *bsaeUrl = nil;
    if (!serverAddress) {
        //根据前端与后台约定好的规则进行解析即可
        //        if ([responseObject[@"State"] boolValue]) {
        //            success(responseObject);
        //        }else{
        //            NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%@",responseObject[@"PromptMessage"]]                                                                   forKey:NSLocalizedDescriptionKey];
        //            NSError *aError = [NSError errorWithDomain:@"Custom" code:-119 userInfo:userInfo];
        //            failure(aError);
        //        }
        
    } else {
        bsaeUrl = [serverAddress stringByAppendingPathComponent:portAddress];
    }
    
    [manager POST:bsaeUrl parameters:parameters success:^(AFHTTPRequestOperation * _Nonnull operation, id  _Nonnull responseObject) {
        success(responseObject);

    } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) {
        failure(error);
    }];
}


+ (void)HTTP_GETWithServerAddress:(NSString *)serverAddress portAddress:(NSString *)portAddress parameters:(NSMutableDictionary *)parameters success:(void (^)(id))success failure:(void (^)(NSError *))failure{
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = 10.0f;
    NSString *baseUrl = nil;
    if (!serverAddress) {
        baseUrl = [@"服务器地址" stringByAppendingPathComponent:portAddress];
    } else {
        baseUrl = [serverAddress stringByAppendingPathComponent:portAddress];
    }
    [manager GET:baseUrl parameters:parameters success:^(AFHTTPRequestOperation * _Nonnull operation, id  _Nonnull responseObject) {
        success(responseObject);
    } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) {
        failure(error);
    }];
}
@end

项目中如何使用,以多个异步请求为例;

#import "ViewController.h"
#import "HTTPTool.h"
#import "AFNetworking.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    NSMutableDictionary *parameter = [NSMutableDictionary dictionary];
    parameter[@"useraccount"] = @"13141140620";
    parameter[@"userpwd"] = @"123456";
    __weak typeof (self) weakSelf = self;
    AFHTTPRequestOperation *op1 = [HTTPTool HTTP_Method:@"POST" serverAddress:nil portAddress:@"端口号1" parameters:parameter success:^(id responseObject) {
//        <#code#>
    } failure:^(NSError *error) {
//        <#code#>
    }];
    
AFHTTPRequestOperation *op2 =  [HTTPTool HTTP_Method:@"GET" serverAddress:nil portAddress:@"端口号2" parameters:parameter success:^(id responseObject) {
        //        <#code#>
    } failure:^(NSError *error) {
        //        <#code#>
    }];
    
    NSArray *array = [AFHTTPRequestOperation batchOfRequestOperations:@[op1,op2] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
//        <#code#>
    } completionBlock:^(NSArray * _Nonnull operations) {
//        完成请求后操作
    }];
    [[NSOperationQueue mainQueue] addOperations:array waitUntilFinished:NO];
}
@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值