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]; 
相关文章
相关标签/搜索