AFNetWorking用法及緩存處理
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請求使用流程就完成了。