AFNNetworking 2.0你相信你一定知道AFNNetworking,不知道你還可以看看該作者的博文踩官,所以我就不多說關于它的強大之處了却桶,AFNetworking 提供了比NSURLSession更高層次的抽象,這篇文章主要總結(jié)AFNNetworking 2.0的幾個常用方法蔗牡。1).GET和POST請求GET:- (NSURLSessionDataTask *)GET:(NSString *)URLString? ? ? ? ? ? ? ? ? parameters:(id)parameters? ? ? ? ? ? ? ? ? ? ? success:(void (^)(NSURLSessionDataTask *task, id responseObject))success? ? ? ? ? ? ? ? ? ? ? failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failurePOST:- (NSURLSessionDataTask *)POST:(NSString *)URLString? ? ? ? ? ? ? ? ? ? parameters:(id)parameters? ? ? ? ? ? ? ? ? ? ? success:(void (^)(NSURLSessionDataTask *task, id responseObject))success? ? ? ? ? ? ? ? ? ? ? failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure在實際的開發(fā)中颖系,我比較習慣把第三方的代碼進行一層封裝,如下我們把GET和POST請求封裝起來://GET+ (void)getWithPath:(NSString *)path params:(NSDictionary *)params success:(HttpSuccessBlock)success failure:(HttpFailureBlock)failure{? ? [self requestWithPath:path params:params success:success failure:failure method:@"GET"];}//POST+ (void)postWithPath:(NSString *)path params:(NSDictionary *)params success:(HttpSuccessBlock)success failure:(HttpFailureBlock)failure{? ? [self requestWithPath:path params:params success:success failure:failure method:@"POST"];}typedef void (^HttpSuccessBlock)(id JSON);typedef void (^HttpFailureBlock)(NSError *error);...省略+ (void)requestWithPath:(NSString *)path params:(NSDictionary *)params success:(HttpSuccessBlock)success failure:(HttpFailureBlock)failure method:(NSString *)method{? ? AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:kBaseURL]];? ? manager.responseSerializer = [AFJSONResponseSerializer serializer];? ? manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain",@"application/json", @"text/json", @"text/javascript", @"text/html", nil];? ? if ([method? isEqual: @"GET"]) {? ? ? ? [manager GET:path parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {? ? ? ? ? ? success(responseObject);? ? ? ? } failure:^(NSURLSessionDataTask *task, NSError *error) {? ? ? ? ? ? NSLog(@"fail Get!!%@",error);? ? ? ? ? ? failure(error);? ? ? ? }];? ? }else if ([method isEqual:@"POST"]){? ? ? ? [manager POST:path parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {? ? ? ? ? ? NSLog(@"POST成功:%@",responseObject);? ? ? ? ? ? success(responseObject);? ? ? ? } failure:^(NSURLSessionDataTask *task, NSError *error) {? ? ? ? ? ? NSLog(@"fail POST!!%@",error);? ? ? ? ? ? failure(error);? ? ? ? }];? ? }}你有沒有注意到上面我設置了如下代碼:manager.responseSerializer = [AFJSONResponseSerializer serializer];manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain",@"application/json", @"text/json", @"text/javascript", @"text/html", nil];因為AFNetworking的responseSerializer 屬性只能默認只能處理特定的Content-Type辩越,如果你想處理"text/html"等其它類型嘁扼,你需要明確指定它的acceptableContentTypes。2).多文件上傳如下黔攒,這是我寫的第三方微博客戶端中多圖上傳的實例代碼:[manager POST:@"2/statuses/upload.json"? ? ? ? ? parameters:@{@"access_token": accseeToken,? ? ? ? ? ? ? ? ? ? ? ? ? @"status" : encodeStatus,? ? ? ? ? ? ? ? ? ? ? ? ? @"visible" : @(_intVisible),? ? ? ? ? ? ? ? ? ? ? ? ? @"lat" : @(_latitude),? ? ? ? ? ? ? ? ? ? ? ? ? @"long" : @(_longtitude)}? ? ? ? ? ? constructingBodyWithBlock:^(idformData) {? ? ? ? ? ? ? ? NSMutableArray *images = [NSMutableArray arrayWithArray:weakSelf.images];? ? ? ? ? ? ? ? for (id asset in images) {? ? ? ? ? ? ? ? ? ? NSData *data = nil;? ? ? ? ? ? ? ? ? ? if ([asset isKindOfClass:[UIImage class]]) {? ? ? ? ? ? ? ? ? ? ? ? data = UIImageJPEGRepresentation(asset, 0.4);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? if ([asset isKindOfClass:ALAsset.class]) {? ? ? ? ? ? ? ? ? ? ? ? UIImage *original = [UIImage imageWithCGImage: [[asset defaultRepresentation] fullScreenImage]];? ? ? ? ? ? ? ? ? ? ? ? data = UIImageJPEGRepresentation(original, 0.4);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? [formData appendPartWithFileData:data name:@"pic" fileName:@"pic.jpg" mimeType:@"multipart/form-data"];? ? ? ? ? ? ? ? }? ? ? ? ? ? } success:^(NSURLSessionDataTask *task, id responseObject) {? ? ? ? ? ? ? ? NSLog(@"發(fā)送成功");? ? ? ? ? ? ? ? [self back];? ? ? ? ? ? } failure:^(NSURLSessionDataTask *task, NSError *error) {? ? ? ? ? ? ? ? [self showFailHUD];? ? ? ? ? ? }];3).多線程操作如果你需要開啟多個線程, 你需要使用AFHTTPRequestSerializer趁啸,AFHTTPRequestOperation和NSOperationQueue以下是AFNetworking的實例代碼NSMutableArray *mutableOperations = [NSMutableArray array];for (NSURL *fileURL in filesToUpload) {? ? NSURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(idformData) {
[formData appendPartWithFileURL:fileURL name:@"images[]" error:nil];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[mutableOperations addObject:operation];
}
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[...] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
NSLog(@"%lu of %lu complete", numberOfFinishedOperations, totalNumberOfOperations);
} completionBlock:^(NSArray *operations) {
NSLog(@"All operations in batch complete");
}];
[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];
3).網(wǎng)絡狀態(tài)檢查
網(wǎng)絡狀態(tài)檢查在早期都是通過蘋果官方的Reachability類進行檢查,但是這個類本身存在一些問題,并且官方后來沒有再更新亏钩。我們可以直接使用AFNetworking框架檢測莲绰。不管使用官方提供的類還是第三方框架,用法都是類似的姑丑,通常是發(fā)送一個URL然后去檢測網(wǎng)絡狀態(tài)變化蛤签,網(wǎng)絡改變后則調(diào)用相應的網(wǎng)絡狀態(tài)改變方法。如下:
-(void)alert:(NSString *)message{
UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"System Info" message:message delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles: nil];
[alertView show];
}
-(void)checkNetworkStatus{
//創(chuàng)建一個用于測試的url
NSURL *url=[NSURL URLWithString:@"http://www.apple.com"];
AFHTTPRequestOperationManager *operationManager=[[AFHTTPRequestOperationManager alloc]initWithBaseURL:url];
//根據(jù)不同的網(wǎng)絡狀態(tài)改變?nèi)プ鱿鄳幚?/p>
[operationManager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
[self alert:@"2G/3G/4G Connection."];
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
[self alert:@"WiFi Connection."];
break;
case AFNetworkReachabilityStatusNotReachable:
[self alert:@"Network not found."];
break;
default:
[self alert:@"Unknown."];
break;
}
}];
//開始監(jiān)控
[operationManager.reachabilityManager startMonitoring];
}
2.UIWebView
UIWebView不僅能加載網(wǎng)絡資源還可以加載本地資源栅哀,目前支持的常用的文檔格式如:html震肮、pdf称龙、docx、txt等戳晌。
UIWebView整個使用相當簡單:創(chuàng)建URL->創(chuàng)建請求->加載請求鲫尊,無論是加載本地文件還是Web內(nèi)容都是這三個步驟。UIWebView內(nèi)容加載事件同樣是通過代理通知外界沦偎,常用的代理方法如開始加載疫向、加載完成、加載出錯等豪嚎,這些方法通成ν眨可以幫助開發(fā)者更好的控制請求加載過程。
加載資源:
- (void)loadRequest:(NSURLRequest *)request;
常用的屬性和方法:
//重新加載(刷新)
- (void)reload;
//停?止加載
- (void)stopLoading;
//回退
- (void)goBack;
//前進
- (void)goForward;
//需要進?檢測的數(shù)據(jù)類型
@property(nonatomic) UIDataDetectorTypes dataDetectorTypes
//是否能回退
@property(nonatomic,readonly,getter=canGoBack) BOOL canGoBack;
//是否能前進
@property(nonatomic,readonly,getter=canGoForward) BOOL canGoForward;
//是否正在加載中
@property(nonatomic,readonly,getter=isLoading) BOOL loading;
//是否伸縮內(nèi)容至適應屏幕當前尺寸
@property(nonatomic) BOOL scalesPageToFit;
遵守UIWebViewDelegate協(xié)議侈询,監(jiān)聽UIWebView的加載過程:
//開始發(fā)送請求(加載數(shù)據(jù))時調(diào)用:
- (void)webViewDidStartLoad:(UIWebView *)webView;
//請求完畢(加載數(shù)據(jù)完畢)時調(diào)?:
- (void)webViewDidFinishLoad:(UIWebView *)webView;
//請求錯誤時調(diào)用:
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;
//監(jiān)聽UIWebView的加載過程:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
下面是一個例子:
在storyBoard中拖入如下控件:
searchBar的代理方法:
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[self request:_searchBar.text];
[searchBar resignFirstResponder];
}
加載searchBar中的請求:
-(void)request:(NSString *)urlStr{
//創(chuàng)建url
NSURL *url;
//如果file://開頭的字符串則加載bundle中的文件
if([urlStr hasPrefix:kFILEPROTOCOL]){
//取得文件名
NSRange range= [urlStr rangeOfString:kFILEPROTOCOL];
NSString *fileName=[urlStr substringFromIndex:range.length];
url=[[NSBundle mainBundle] URLForResource:fileName withExtension:nil];
}else if(urlStr.length>0){
//如果是http請求則直接打開網(wǎng)站
if ([urlStr hasPrefix:@"http"]) {
url=[NSURL URLWithString:urlStr];
}else{//如果不符合任何協(xié)議則進行搜索
urlStr=[NSString stringWithFormat:@"http://m.bing.com/search?q=%@",urlStr];
}
urlStr=[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];//url編碼
url=[NSURL URLWithString:urlStr];
}
//創(chuàng)建請求
NSURLRequest *request=[NSURLRequest requestWithURL:url];
//加載請求頁面
[_webView loadRequest:request];
}
WebView的代理方法:
-(void)webViewDidStartLoad:(UIWebView *)webView{
//顯示網(wǎng)絡請求加載
[UIApplication sharedApplication].networkActivityIndicatorVisible=true;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
//隱藏網(wǎng)絡請求加載圖標
[UIApplication sharedApplication].networkActivityIndicatorVisible=false;
//設置按鈕狀態(tài)
[self setBarButtonStatus];
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
NSLog(@"error detail:%@",error.localizedDescription);
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"系統(tǒng)提示" message:@"網(wǎng)絡連接發(fā)生錯誤!" delegate:self cancelButtonTitle:nil otherButtonTitles:@"確定", nil];
[alert show];
}
設置前進后退按鈕:
-(void)setBarButtonStatus{
if (_webView.canGoBack) {
_barButtonBack.enabled=YES;
}else{
_barButtonBack.enabled=NO;
}
if(_webView.canGoForward){
_barButtonForward.enabled=YES;
}else{
_barButtonForward.enabled=NO;
}
}
運行結(jié)果如下:
你可以在這里下載到代碼舌涨。
- (void)getAccessToken:(NSString *)requestToken
{
[HttpTool postWithPath:@"oauth2/access_token" params:@{
@"client_id" : kAppKey,
@"client_secret" : kAppSecret,
@"grant_type" : @"authorization_code",
@"redirect_uri" : kRedirectURI,
@"code" : requestToken
} success:^(id JSON) {
// 保存賬號信息
Account *account = [[Account alloc] init];
account.accessToken = JSON[@"access_token"];
account.uid = JSON[@"uid"];
[[AccountTool sharedAccountTool] saveAccount:account];
// 回到主頁面
ViewController *main = [[ViewController alloc]init];
if (main) {
[self presentViewController:main animated:YES completion:nil];
}
} failure:^(NSError *error) {
}];
}