IT虾米网

AFNetWorking用法及缓存处理详解

shasha 2018年06月23日 手机开发 417 0

AFNetWorking 在IOS开发中是一个经常会用的第三方开源库,其最好处是维护及时,源码开源。

常用GET与POST请求方法:

POST请求:

//初始化一个请求对象  
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
  NSString * url = @"你的请求地址"; 
  //dic 为参数字典 
 [manager POST:url parameters:dic success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    //请求成功的回调 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    //请求失败的回调     
    }];

GET请求:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
 NSString * url = @"你的请求地址"; 
   [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    //请求成功的回调 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    //请求失败的回调    
    }];

这里有一个地方需要注意,

[AFHTTPRequestOperationManager manager]

这个类方法我们点进源码可以发现:

+ (instancetype)manager { 
    return [[self alloc] initWithBaseURL:nil]; 
}

这里初始化了一个返回了一个新的对象,并不是单例。

使用这样的下载方法,下载完成后的数据AFNetWorking会帮我们自动解析,但是有时候服务器给的数据并不标准,这时我们需要加上这个设置:


manager.responseSerializer = [AFHTTPResponseSerializer serializer];

这样我们将得到原始的HTTP返回给我们数据。

我们再来探究一下,下载成功后,回调方法里的参数到底是什么东西


success:^(AFHTTPRequestOperation *operation, id responseObject)

其中,第二个参数 responseObject 是下载下来的data数据,可直接进行JSON等解析。

第一个参数,是个AFHTTPRequestOperation对象,来看源文件

@interface AFHTTPRequestOperation : AFURLConnectionOperation 
 
@property (readonly, nonatomic, strong) NSHTTPURLResponse *response; 
 
@property (nonatomic, strong) AFHTTPResponseSerializer <AFURLResponseSerialization> * responseSerializer; 
 
@property (readonly, nonatomic, strong) id responseObject; 
 
@end

可以发现,里面有一个成员便是responseObject,同时,AFHTTPRequestOperation是继承于AFURLConnectionOperation,我们在看看AFURLConnectionOperation这个类:

@interface AFURLConnectionOperation : NSOperation <NSURLConnectionDelegate, NSURLConnectionDataDelegate, NSSecureCoding, NSCopying> 
 
@property (nonatomic, strong) NSSet *runLoopModes; 
 
@property (readonly, nonatomic, strong) NSURLRequest *request; 
 
@property (readonly, nonatomic, strong) NSURLResponse *response; 
 
@property (readonly, nonatomic, strong) NSError *error; 
 
@property (readonly, nonatomic, strong) NSData *responseData; 
 
@property (readonly, nonatomic, copy) NSString *responseString; 
 
@property (readonly, nonatomic, assign) NSStringEncoding responseStringEncoding; 
 
@property (nonatomic, assign) BOOL shouldUseCredentialStorage; 
 
@property (nonatomic, strong) NSURLCredential *credential; 
 
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy; 
 
@property (nonatomic, strong) NSInputStream *inputStream; 
 
@property (nonatomic, strong) NSOutputStream *outputStream; 
 
@property (nonatomic, strong) dispatch_queue_t completionQueue; 
 
@property (nonatomic, strong) dispatch_group_t completionGroup; 
 
@property (nonatomic, strong) NSDictionary *userInfo; 
 
- (instancetype)initWithRequest:(NSURLRequest *)urlRequest NS_DESIGNATED_INITIALIZER; 
 
- (void)pause; 
 
- (BOOL)isPaused; 
 
- (void)resume;

看到这里,就离AFNETWorking封装的源头很近了,里面的成员非常多,其中包含了大部分我们需要的信息,可以通过点语法取到,其中有输入输出流,错误信息,请求到的Data数据,以及请求到的字符串数据 

responseString

我们可以通过

NSLog ( @"operation: %@" , operation. responseString );

来打印查看请求到的原始信息。

几点注意:

1.关于崩溃url为nil

大多数这样的原因是url中有特殊字符或者中文字符,AFNETWorking并没有做UTF8的转码,需要:

url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

2.添加HttpHead字段的方法

 //为这个下载任务HTTP头添加@"User-Agent"字段 
 [manager.requestSerializer setValue:_scrData forHTTPHeaderField:@"User-Agent"]; 
 //打印头信息 
    NSLog(@"%@",manager.requestSerializer.HTTPRequestHeaders);

在下载请求中,经常会请求一些不长变化的数据,如果每次APP启动都进行请求,会消耗许多资源,并且有时候缓存的处理,可以大大改善用户体验。

在AFNETWorking中,并没有提供现成的缓存方案,我们可以通过写文件的方式,自行做缓存。

在下载方法中:

[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
        //写缓存 
        NSString *cachePath = @"你的缓存路径";//  /Library/Caches/MyCache 
        [data writeToFile:cachePath atomically:YES]; 
                succsee(data); 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    }];

然后在每次下载前,进行如下判断:

 NSString * cachePath = @"你的缓存路径"; 
        if ([[NSFileManager defaultManager] fileExistsAtPath:cachePath]) { 
            //从本地读缓存文件 
            NSData *data = [NSData dataWithContentsOfFile:cachePath]; 
            }

有时,我们的下载请求可能是用户的动作触发的,比如一个按钮。我们还应该做一个保护机制的处理,

//初始化一个下载请求数组 
NSArray * requestArray=[[NSMutableArray alloc]init]; 
//每次开始下载任务前做如下判断 
for (NSString * request in requestArray) { 
        if ([url isEqualToString:request]) { 
            return; 
        } 
    } 
 [requestArray addObject:url]; 
 //下载成功或失败后 
 [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
        [requestArray removeObject:url] 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
        [requestArray removeObject:url] 
    }];

至此,一个比较完成AFNETWorking请求使用流程就完成了。




发布评论

分享到:

IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

iOS图片无损拉伸详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。