IOS開發網絡數據---- AFNetworking的使用

http網絡庫是集XML解析,Json解析,網絡圖片下載,plist解析,數據流請求操做,上傳,下載,緩存等網絡衆多功能於一身的強大的類庫。最新版本支持session,xctool單元測試。網絡獲取數據一直是手機軟件的重中之重,若是處理的很差,會形成不好的用戶體驗。隨着ASIHTTPRequest的中止更新,更換網絡庫是必然的事情,AFNetworking就是很好的替代品。並且都是輕量級,不要擔憂加入太多庫會多軟件性能有影響。
1.爲何用第三方網絡庫?先說若是不用網絡庫,我曾有一次以爲什麼都用蘋果原生的好,XML解析用蘋果自帶的委託,下載圖片本身寫,若是你也有跟我同樣的經歷,那你會發現本身管理起來很複雜,很容易出錯。並且性能很差。若是你是一個追求完美的人,那就放下你的執拗,就如當初的我同樣,嘗試一下網絡庫吧。
2.爲何要用AFNetworking?第一點,它有人更新和維護,並且目前使用者不少,第二點,仍是使用者不少,那麼他的資料,文檔,demo就多,很好找遇到問題好解決。若是不用AFNetworking,還有一種MKNetworkKit也不錯,不妨一試。
如何選擇AFNetworking版本

首先得下載AFNetworking庫文件,下載時得首先弄清楚,你將要開發的軟件兼容的最低版本是多少。AFNetworking 2.0或者以後的版本須要xcode5.0版本而且只能爲IOS6或更高的手機系統上運行,若是開發MAC程序,那麼2.0版本只能在MAC OS X 10.8或者更高的版本上運行。php

若是你想要兼容IOS5或MAC OS X 10.7,那你須要用最新發布的1.x版本
若是要兼容4.3或者MAC OS X 10.6, 須要用最新發布的0.10.x版本
 
2013年大多數軟件兼容的最低版本爲4.3,而2014年,估計大多數軟件兼容的最低版本將會是5.0甚至6.0;
因此, 目前最好的選擇仍是1.x版本,兼容到IOS5.0。
如何經過URL獲取json數據
第一種,利用AFJSONRequestOperation,官方網站上給的例子:

    NSString *str=[NSString stringWithFormat:@"https://alpha-api.app.net/stream/0/posts/stream/global"];html

    NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];nginx

    NSURLRequest *request = [NSURLRequest requestWithURL:url];git

    //    從URL獲取json數據github

    AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:requestsuccess:^(NSURLRequest *request, NSHTTPURLResponse *response, NSDictionary* JSON) {web

                NSLog(@"獲取到的數據爲:%@",JSON);json

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id data) {api

        NSLog(@"發生錯誤!%@",error);xcode

    }];緩存

    [operation1 start];

 

第二種方法,利用AFHTTPRequestOperation 先獲取到字符串形式的數據,而後轉換成json格式,將NSString格式的數據轉換成json數據,利用IOS5自帶的json解析方法:

   NSString *str=[NSString stringWithFormat:@"https://alpha-api.app.net/stream/0/posts/stream/global"];

    NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

   AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSString *html = operation.responseString;

             NSData* data=[html dataUsingEncoding:NSUTF8StringEncoding];

             id dict=[NSJSONSerialization  JSONObjectWithData:data options:0 error:nil];

        NSLog(@"獲取到的數據爲:%@",dict);

    }failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"發生錯誤!%@",error);

    }];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    [queue addOperation:operation];

 

 

若是發生Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x14defc80 {NSUnderlyingError=0x14deea10 "bad URL", NSLocalizedDescription=bad URL這個錯誤,請檢查URL編碼格式。有沒有進行stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding

 

 

如何經過URL獲取圖片

異步獲取圖片,經過隊列實現,並且圖片會有緩存,在下次請求相同的連接時,系統會自動調用緩存,而不從網上請求數據。


UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 100.0f, 100.0f, 100.0f)]; 
    [imageView setImageWithURL:[NSURL URLWithString:@"http://i./r4uwx.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]]; 
    [self.view addSubview:imageView];

上面的方法是官方提供的,還有一種方法,

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.scott-sherwood.com/wp-content/uploads/2013/01/scene.png"]];

    AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image) {

        self.backgroundImageView.image = image;

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {

        NSLog(@"Error %@",error);

    }];

 

    [operation start];

 

若是使用第一種URLWithString:  placeholderImage:會有更多的細節處理,其實實現仍是經過AFImageRequestOperation處理,能夠點擊URLWithString:  placeholderImage:方法進去看一下就一目瞭然了。因此我以爲仍是用第一種好。

 

如何經過URL獲取plist文件

經過url獲取plist文件的內容,用的不多,這個方法在官方提供的方法裏面沒有

    NSString *weatherUrl = @"http://www.calinks.com.cn/buick/kls/Buickhousekeeper.plist";

    NSURL *url = [NSURL URLWithString:[weatherUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [AFPropertyListRequestOperation addAcceptableContentTypes:[NSSet setWithObject:@"text/plain"]];

    AFPropertyListRequestOperation *operation = [AFPropertyListRequestOperation propertyListRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id propertyList) {

        NSLog(@"%@",(NSDictionary *)propertyList);

        

    }failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id propertyList) {

        NSLog(@"%@",error);

    }];

 

    [operation start];

若是稍不留神,可能就出現Error Domain=AFNetworkingErrorDomain Code=-1016 "Expected content type {(

    "application/x-plist"

)}, got text/plain" UserInfo=0x16e91ce0 {NSLocalizedRecoverySuggestion=

 

...

...

, AFNetworkingOperationFailingURLRequestErrorKey= { }, NSErrorFailingURLKey=, NSLocalizedDescription=Expected content type {(

    "application/x-plist"

)}, got text/plain, AFNetworkingOperationFailinponseErrorKey= { URL:  } { status code: 200, headers {

    "Accept-Ranges" = bytes;

    Connection = "keep-alive";

    "Content-Length" = 974;

    "Content-Type" = "text/plain";

    Date = "Sat, 25 Jan 2014 07:29:26 GMT";

    Etag = ""1014c2-3ce-4ee63e1c80e00"";

    "Last-Modified" = "Wed, 25 Dec 2013 23:04:24 GMT";

    Server = "nginx/1.4.2";

 

} }}

可能還會出現亂碼,解決辦法就是[AFPropertyListRequestOperation addAcceptableContentTypes:[NSSet setWithObject:@"text/plain"]];

 

 

如何經過URL獲取XML數據

xml解析使用AFXMLRequestOperation,須要實現蘋果自帶的NSXMLParserDelegate委託方法,XML中有一些不須要的協議格式內容,因此就不能像json那樣解析,還得實現委託。我以前有想過可否全部的XML連接用一個類處理,並且跟服務端作了溝通,結果很不方便,效果很差。XML大多標籤不一樣,格式也不固定,因此就有問題,使用json就要方便的多。

第一步;在.h文件中加入委託NSXMLParserDelegate

第二步;在.m文件方法中加入代碼

    NSURL *url = [NSURL URLWithString:@"http://113.106.90.22:5244/sshopinfo"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    AFXMLRequestOperation *operation =

    [AFXMLRequestOperation XMLParserRequestOperationWithRequest:request success:^(NSURLRequest *request,NSHTTPURLResponse *response, NSXMLParser *XMLParser) {

        XMLParser.delegate = self;

        [XMLParser setShouldProcessNamespaces:YES];

        [XMLParser parse];

    }failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser*XMLParser) {

        NSLog(@"%@",error);

    }];

    [operation start];

第三步;在.m文件中實現委託方法

    //在文檔開始的時候觸發

-(void)parserDidStartDocument:(NSXMLParser *)parser{

    NSLog(@"解析開始!");

}

//解析起始標記

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{

    NSLog(@"標記:%@",elementName);

    

}

//解析文本節點

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{

    NSLog(@"值:%@",string);

}

//解析結束標記

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString *)qName{

    NSLog(@"結束標記:%@",elementName);

}

//文檔結束時觸發

-(void) parserDidEndDocument:(NSXMLParser *)parser{

    NSLog(@"解析結束!");

}

運行的結果:iOS開發網絡數據之AFNetworking使用


如何使用AFHTTPClient進行web service操做
AFHTTPClient處理GET 和 POST請求.作網頁的朋友們這個方法用的比較多。在要常常調用某個請求時,能夠封裝,節省資源。

   BaseURLString = @"http://www.raywenderlich.com/downloads/weather_sample/";

    NSURL *baseURL = [NSURL URLWithString:[NSString stringWithFormat:BaseURLString]];

    NSDictionary *parameters = [NSDictionary dictionaryWithObject:@"json" forKey:@"format"];

    AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];

    

    [client registerHTTPOperationClass:[AFJSONRequestOperation class]];

    [client setDefaultHeader:@"Accept" value:@"text/html"];

    [client postPath:@"weather.php" parameters:parameters success:^(AFHTTPRequestOperation *operation,id responseObject) {

        NSString* newStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];

        NSLog(@"POST請求:%@",newStr);

    }failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"%@",error);

    }];

    

    [client getPath:@"weather.php" parameters:parameters success:^(AFHTTPRequestOperation *operation, idresponseObject) {

        NSString* newStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];

        NSLog(@"GET請求:%@",newStr);

    }failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"%@",error);

    }];

 

運行結果:iOS開發網絡數據之AFNetworking使用

若是須要顯示網絡活動指示器,能夠用下面方法:
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;

 

Error: Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: text/html" UserInfo=0x16774de0 {NSErrorFailingURLKey=http://192.168.2.2:8181/ecar/tsp/uploadLocation?CID=781666&serviceType=1, AFNetworkingOperationFailinponseErrorKey= { URL: http://192.168.2.2:8181/ecar/tsp/uploadLocation?CID=781666&serviceType=1 } { status code: 200, headers {

    XXX

 

} }, NSLocalizedDescription=Request failed: unacceptable content-type: text/html}

返回數據格式不對。註銷這句話: op.responseSerializer = [AFJSONResponseSerializerserializer];而後將返回的數據本身轉換。

 

 

 

error = Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/html" UserInfo=0x1740f2c00 {com.alamofire.serialization.response.error.response= { URL: http://192.168.5.132/api/cats?type=apps } { status code: 200, headers {

    Connection = "keep-alive";

    "Content-Type" = "text/html; charset=utf-8";

    Date = "Thu, 05 Nov 2015 10:27:42 GMT";

    Server = nginx;

    "Transfer-Encoding" = Identity;

} }

 

 

AF能夠接受json之外的數據    本身隨意定義的格式均可以    只不過要使用AFNetwork提供的解析方法的話   它只對通用的格式作處理    你返回的數據不是那種格式   他就沒法解析出來     那要你本身處理    改變AFNetWork的庫文件     找到他判斷錯誤的那個函數    讓他從正確的方法返回     若是你不會的話  就在返回錯誤的方法處理也能夠   反正數據已經到了       網絡的目的   是爲了獲得數據    你的數據已經到了   只不過AFNetwork認定你的數據不符合經常使用的格式      確實也不符合   由於你的數據是加密的東西  並且是對整個json格式加密   而不是隻對值加密    因此要實現這種格式的傳輸    只能修改AFNetwork的庫    而你不會    那就先這麼用着

 

 

舉個例子    大家如今的作法是對整個字符串加密    若是你不這麼作    只將值部分加密  而不對鍵加密    就是{「message」:「值的密文」}   那麼這個數據仍然符合json格式   AFNetwork依然能解析出來       大家對整個json字符串都加密了  那密文就不是json格式了       因此大家能夠按我說的改  僅加密值部分     也就按照如今的方法    在錯誤的返回方法裏面處理數據    可是你本身知道數據是正確的   只不過AFNetwork誤判了而已        這個屬於原理上東西    改不了     要麼就是不讓AFNetwork解析      他只透傳    你本身解析    若是讓他幫你解析   你就要指定一個格式給他    指定了格式  而你的數據不符合格式   那就是按錯誤的方法返回   

AFNetworking關於HTTP認證的問題

 

AFNetwork實現basic認證的方法很簡單

http://stackoverflow.com/questions/12440059/using-afnetworking-and-http-basic-authentication

iOS開發網絡數據之AFNetworking使用

AFNetwork實現digest認證

iOS開發網絡數據之AFNetworking使用
建立一個NSURLCredential對象,而後將對象賦值到請求
iOS開發網絡數據之AFNetworking使用

 
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:@"Username" password:@"Password" persistence:NSURLCredentialPersistenceForSession]; [manager setCredential:credential]; 
相關文章
相關標籤/搜索