iOS-网络(二)--AFNetWorking

之前有总结iOS原生网络的使用,今天来总结一下基于NSURLSession封装的优秀开源框架AFNetWorking。

不知道有没人和我一样,接触网络是从AFNetWorking开始的,那个时候就觉得AFNetWorking是相当的优秀,极大的降低了iOS开发工程师处理网络请求的难度,让iOS开发变成一件愉快的事情,当然现在也是这么觉得,因为自己还没有接触文件的上传下载,所以这篇文章只说HTTP的两个请求:Get和Post。

1.AFHTTPSessionManager

AFHTTPSessionManager请求管理者,是为了便利使用HTTP请求,当一个baseURL提供时,用相对路径构造GET/POST等便利的方法创建请求,扒出部分源码声明如下:

@interfaceAFHTTPSessionManager:AFURLSessionManager
// 当baseURL提供时,用相对路径构造GET/POST等便利方法来创建请求
@property (readonly, nonatomic, strong, nullable) NSURL *baseURL;
// 请求数据序列化
@property (nonatomic, strong) AFHTTPRequestSerializer <AFURLRequestSerialization> * requestSerializer;
// 响应数据序列化   
@property (nonatomic, strong) AFHTTPResponseSerializer <AFURLResponseSerialization> * responseSerializer;                                                                                                                                                     
// 创建会话使用的安全策略  
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;                                                                                                                                              
// 创建并返回一个‘AFHTTPSessionManager’对象 
+ (instancetype)manager;                                                                                                                          
// 使用指定的基本URL初始化对象   
- (instancetype)initWithBaseURL:(nullable NSURL *)url;                                                                                                                                                   
//Get请求
- (NSURLSessionDataTask *)GET:(NSString *)URLString

                   parameters:(id)parameters

                      success:(void(^)(NSURLSessionDataTask*task,idresponseObject))success

                      failure:(void(^)(NSURLSessionDataTask*task,NSError*error))failure

{

    return[selfGET:URLStringparameters:parametersprogress:nilsuccess:successfailure:failure];

}
//Post请求
- (NSURLSessionDataTask *)POST:(NSString *)URLString

                    parameters:(id)parameters

                       success:(void(^)(NSURLSessionDataTask*task,idresponseObject))success

                       failure:(void(^)(NSURLSessionDataTask*task,NSError*error))failure

{

    return[selfPOST:URLStringparameters:parametersprogress:nilsuccess:successfailure:failure];

}

@end

处理Get请求

 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    NSString*urlString =  @"http://localhost:3030/userinfo";

   NSDictionary *parameters=@{@"name":@"zyp",@"pwd":@"666"};

    [manager GET:urlString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

         NSLog(@"请求成功");

    }failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        NSLog(@"请求失败");

    }];

处理Post请求

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    NSString*urlString =  @"http://localhost:3030/userinfo";

NSDictionary *parameters=@{@"name":@"zhaoyipei",@"pwd":@"yang"};

[manager POST:urlString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

         NSLog(@"请求成功");

}failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        NSLog(@"请求失败");

    }];

AFNetWorking内存泄露
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];一般来说,我们会认为,这个manager是个单例,但是我们来看一下源码:

+ (instancetype)manager {

    return [[[self class] alloc] initWithBaseURL:nil];

}

然后发现被骗了,它其实是每次都实例化一个AFHTTPSessionManager对象,所以必要的时候需要自己封装一下。
简单实现NSURLSession封装
.h文件

//请求序列化格式

typedef enum {

    HTTPRequestSerializationURLEncoded =0,

    HTTPRequestSerializationJSON

} HTTPRequestSerializationType;

@interface HTTPRequestManager : NSObject

+ (instancetype)manager;

@property (nonatomic, assign) HTTPRequestSerializationType serializationType;

- (void)GET:(NSString *)URL

 parameters:(NSDictionary *)parameters

    success:(void(^)(idobject))success

    failure:(void(^)(NSError*error))failure;

- (void)POST:(NSString *)URL

  parameters:(NSDictionary *)parameters

     success:(void(^)(idobject))success

     failure:(void(^)(NSError*error))failure;

@end

.m文件

#import "HTTPRequestManager.h"

@implementation HTTPRequestManager

+ (instancetype)manager
{
    return [[self alloc] init];
}

- (void)GET:(NSString *)URL
 parameters:(NSDictionary *)parameters
    success:(void (^)(id _Nonnull))success
    failure:(void (^)(NSError * _Nonnull))failure
{
    if (URL.length == 0) {
        if (failure) {
            failure([NSError errorWithDomain:@"123" code:-1 userInfo:nil]);
        }
        return;
    }
    //Get请求的内容是拼接在URL后面的,所以要通过NSURLComponents对parameters进行处理
    NSURLComponents *URLcomponents = [NSURLComponents componentsWithString:URL];
    NSArray *old = URLcomponents.queryItems;
    NSMutableArray *array = old ? [old mutableCopy] : [NSMutableArray new];   
    [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        
        NSURLQueryItem *queryItem = [NSURLQueryItem queryItemWithName:key value:obj];
        [array addObject:queryItem];
    }];
    
    URLcomponents.queryItems = array;
    
    // 1.创建请求会话
    NSURLSession *session = [NSURLSession sharedSession];
    
    // 2.创建请求
    NSURLRequest *request = [NSURLRequest requestWithURL:URLcomponents.URL];
    // 3.创建请求任务
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            if (failure) {
                failure(error);
            }
            return;
        }
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
        if (success) {
            success(json);
        }
    }];
    // 4.开始任务
    [task resume];
}

- (void)POST:(NSString *)URL
  parameters:(NSDictionary *)parameters
     success:(void (^)(id _Nonnull))success
     failure:(void (^)(NSError * _Nonnull))failure
{
    NSURL *requestURL = [NSURL URLWithString:URL];
    NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:requestURL];
    mRequest.HTTPMethod = @"POST";
    //根据MIME类型,对parameters进行处理
    if (parameters.count) {
        if (self.serializationType == HTTPRequestSerializationJSON) {
            [mRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
            mRequest.HTTPBody = [NSJSONSerialization dataWithJSONObject:parameters options:kNilOptions error:NULL];
        } else {
            [mRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
            NSMutableArray *array = [[NSMutableArray alloc]initWithCapacity:parameters.count];
            [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
                [array addObject:[NSString stringWithFormat:@"%@=%@", key, obj]];
            }];
            NSString *urlEncode = [array componentsJoinedByString:@"&"];
            mRequest.HTTPBody = [urlEncode dataUsingEncoding:NSUTF8StringEncoding];
        }
    }
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:mRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            if (failure) {
                failure(error);
            }
            return;
        }
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
        if (success) {
            success(json);
        }
    }];
    // 4.开始任务
    [task resume];
}
@end

然后呢,就会发现这个看起来太臃肿,并且很明显,在Get请求和Post请求都涉及到NSURLSession和NSURLSessionDataTask,只是在NSURLRequest的处理上有差异,所以我们可以进一步将NSURLSessionDataTask进行封装,完了之后结果如下:

- (void)GET:(NSString *)URL
 parameters:(NSDictionary *)parameters
    success:(void (^)(id _Nonnull))success
    failure:(void (^)(NSError * _Nonnull))failure
{
    if (URL.length == 0) {
        if (failure) {
            failure([NSError errorWithDomain:@"123" code:-1 userInfo:nil]);
        }
        return;
    }
    NSURLComponents *URLcomponents = [NSURLComponents componentsWithString:URL];
    NSArray *old = URLcomponents.queryItems;
    
    NSMutableArray *array = old ? [old mutableCopy] : [NSMutableArray new];
    
    [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        
        NSURLQueryItem *queryItem = [NSURLQueryItem queryItemWithName:key value:obj];
        [array addObject:queryItem];
    }];
    
    URLcomponents.queryItems = array;
    // 2.创建请求
       NSURLRequest *request = [NSURLRequest requestWithURL:URLcomponents.URL];
      [self request:request success:success failure:failure];
}

- (void)POST:(NSString *)URL
  parameters:(NSDictionary *)parameters
     success:(void (^)(id _Nonnull))success
     failure:(void (^)(NSError * _Nonnull))failure
{
    NSURL *requestURL = [NSURL URLWithString:URL];
    NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:requestURL];
    mRequest.HTTPMethod = @"POST";
    if (parameters.count) {
        if (self.serializationType == HTTPRequestSerializationJSON) {
            [mRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
            mRequest.HTTPBody = [NSJSONSerialization dataWithJSONObject:parameters options:kNilOptions error:NULL];
        } else {
            [mRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
            NSMutableArray *array = [[NSMutableArray alloc]initWithCapacity:parameters.count];
            [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
                [array addObject:[NSString stringWithFormat:@"%@=%@", key, obj]];
            }];
            NSString *urlEncode = [array componentsJoinedByString:@"&"];
            mRequest.HTTPBody = [urlEncode dataUsingEncoding:NSUTF8StringEncoding];
        }
    }
    [self request:mRequest success:success failure:failure];
}
- (void)request:(NSURLRequest *)request
            success:(void (^)(id _Nonnull))success
            failure:(void (^)(NSError * _Nonnull))failure {
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            if (failure) {
                failure(error);
            }
            return;
        }
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
        if (success) {
            success(json);
        }
    }];
    // 4.开始任务
    [task resume];
    
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容