http网络库是集XML解析,Json解析,网络图片下载,plist解析,数据流请求操作,上传,下载,缓存等网络众多功能于一身的强大的类库。最新版本支持session,
xctool单元测试
。网络获取数据一直是手机软件的重中之重,如果处理的不好,会造成很差的用户体验。
随着
ASIHTTPRequest
的停止更新,更换网络库是必然的事情,
AFNetworking就是很好的替代品。而且都是轻量级,不要担心加入太多库会多软件性能有影响。
1.
为什么用第三方网络库?先说如果不用网络库,我曾有一次觉得什么都用苹果原生的好,XML解析用苹果自带的委托,下载图片自己写,如果你也有跟我一样的经历,那你会发现自己管理起来很复杂,很容易出错。而且性能不好。如果你是一个追求完美的人,那就放下你的固执,就如当初的我一样,尝试一下网络库吧。
NSString *str=[NSString stringWithFormat:@"https://alpha-api.app.net/stream/0/posts/stream/global"];
NSURL *url =[NSURL URLWithString:[strstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequestrequestWithURL:url];
// 从URL获取json数据
AFJSONRequestOperation *operation1 = [AFJSONRequestOperationJSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSDictionary* JSON) {
NSLog(@"获取到的数据为:%@",JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id data) {
NSLog(@"发生错误!%@",error);
}];
[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 =[[AFHTTPRequestOperationalloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString*html = operation.responseString;
NSData* data=[html dataUsingEncoding:NSUTF8StringEncoding];
id dict=[NSJSONSerialization JSONObjectWithData:dataoptions:0 error:nil];
NSLog(@"获取到的数据为:%@",dict);
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"发生错误!%@",error);
}];
NSOperationQueue *queue = [[NSOperationQueuealloc] 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:[NSURLURLWithString:@"http://www.scott-sherwood.com/wp-content/uploads/2013/01/scene.png"]];
AFImageRequestOperation *operation = [AFImageRequestOperationimageRequestOperationWithRequest:request imageProcessingBlock:nilsuccess:^(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:[weatherUrlstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequestrequestWithURL:url];
[AFPropertyListRequestOperationaddAcceptableContentTypes:[NSSet setWithObject:@"text/plain"]];
AFPropertyListRequestOperation*operation =[AFPropertyListRequestOperationpropertyListRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id propertyList) {
NSLog(@"%@",(NSDictionary *)propertyList);
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id propertyList) {
NSLog(@"%@",error);
}];
[operation start];
如果稍不留神,可能就出现ErrorDomain=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:26GMT";
Etag =""1014c2-3ce-4ee63e1c80e00"";
"Last-Modified" = "Wed, 25 Dec 2013 23:04:24GMT";
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 = [NSURLURLWithString:@"http://113.106.90.22:5244/sshopinfo"];
NSURLRequest *request = [NSURLRequestrequestWithURL:url];
AFXMLRequestOperation *operation =
[AFXMLRequestOperationXMLParserRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {
XMLParser.delegate = self;
[XMLParsersetShouldProcessNamespaces: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 *)parserdidStartElement:(NSString*)elementName namespaceURI:(NSString *)namespaceURIqualifiedName:(NSString *)qNameattributes:(NSDictionary*)attributeDict{
NSLog(@"标记:%@",elementName);
}
//解析文本节点
- (void)parser:(NSXMLParser *)parserfoundCharacters:(NSString*)string{
NSLog(@"值:%@",string);
}
//解析结束标记
- (void)parser:(NSXMLParser *)parserdidEndElement:(NSString*)elementName namespaceURI:(NSString *)namespaceURIqualifiedName:(NSString*)qName{
NSLog(@"结束标记:%@",elementName);
}
//文档结束时触发
-(void)parserDidEndDocument:(NSXMLParser *)parser{
NSLog(@"解析结束!");
}
运行的结果:
如何使用AFHTTPClient进行web service操作
BaseURLString =@"http://www.raywenderlich.com/downloads/weather_sample/";
NSURL*baseURL = [NSURLURLWithString:[NSStringstringWithFormat:BaseURLString]];
NSDictionary *parameters = [NSDictionarydictionaryWithObject:@"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,id responseObject) {
NSString* newStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(@"GET请求:%@",newStr);
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",error);
}];
运行结果:
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: unacceptablecontent-type: text/html}
返回数据格式不对。注销这句话: op.responseSerializer= [AFJSONResponseSerializer serializer];然后将返回的数据自己转换。
error = Error Domain=com.alamofire.error.serialization.responseCode=-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 201510: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