您的位置:首页 > 理论基础 > 计算机网络

iOS开发——网络请求案例汇总

2015-11-26 18:43 591 查看
       在实际的项目开发中,连接网络是每一款App必不可少的基本功能。对于客户端的网络请求而言,无非是有两个实现方向:使用网络请求框架或者不使用网络请求框架。在这篇博客中,我将用苹果自带的网络请求方式(不使用第三方框架)下对iOS网络请求方法做一个汇总。我将在之后的博客中介绍使用AFNetworking框架进行请求的实现。代码已经上传至:https://github.com/chenyufeng1991/iOS-NetworkRequest
  。

【1.使用XML请求SOAP,用NSURLConnectionDelegate实现】

很多网络数据是通过SOAP请求的,http://www.webxml.com.cn/zh_cn/web_services.aspx 。上面有很多不错的接口,我们需要使用SOAP发送XML的方式来实现。我这里来调用手机号码归属地的接口,并OC实现,使用的是苹果自带的NSURLConnectionDelegate代理。请注意,有的WebService
SOAP支持GET,有的支持POST,有的两者都支持。这个就要看服务端了。大家可以分别来进行测试。在该示例中,不支持GET方式,所以我就是用了POST。

实现代码如下:

#import "SOAP1ViewController.h"

@interface SOAP1ViewController ()<NSURLConnectionDelegate>

@property (strong, nonatomic) NSMutableData *webData;
@property (strong, nonatomic) NSURLConnection *conn;

@end

@implementation SOAP1ViewController

- (void)viewDidLoad {
[super viewDidLoad];

[self query:@"18888888888"];

}

-(void)query:(NSString*)phoneNumber{

// 创建SOAP消息,内容格式就是网站上提示的请求报文的主体实体部分    这里使用了SOAP1.2;
NSString *soapMsg = [NSString stringWithFormat:
@"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<soap12:Envelope "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
"xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">"
"<soap12:Body>"
"<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"
"<mobileCode>%@</mobileCode>"
"<userID>%@</userID>"
"</getMobileCodeInfo>"
"</soap12:Body>"
"</soap12:Envelope>", phoneNumber, @""];

NSURL *url = [NSURL URLWithString: @"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:@"%lu", (unsigned long)[soapMsg length]];
[req addValue:@"application/soap+xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
[req setHTTPMethod:@"POST"];
[req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];

self.conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (self.conn) {
self.webData = [NSMutableData data];
}

}

// 刚开始接受响应时调用
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *) response{
[self.webData setLength: 0];
}

// 每接收到一部分数据就追加到webData中
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *) data {

if(data != NULL){
[self.webData appendData:data];
}

}

// 出现错误时
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *) error {
self.conn = nil;
self.webData = nil;
}

// 完成接收数据时调用
-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
NSString *theXML = [[NSString alloc] initWithBytes:[self.webData mutableBytes]
length:[self.webData length]
encoding:NSUTF8StringEncoding];

// 打印出得到的XML
NSLog(@"返回的数据:%@", theXML);

}

@end


打印结果如下:



【2.使用XML请求SOAP,用NSURLConnection实现】

使用上述1的方法显得代码有点多,我们可以用最简单的NSURLConnection来实现,虽然现在已经不推荐使用NSURLConnection。但是我们还是来实现一下。这里采用异步请求的方式实现,就不会阻塞主线程。实现代码如下:

#import "SOAP2ViewController.h"

@interface SOAP2ViewController ()

@property (strong, nonatomic) NSMutableData *webData;
@property (strong, nonatomic) NSURLConnection *conn;

@end

@implementation SOAP2ViewController

- (void)viewDidLoad {
[super viewDidLoad];

[self query:@"18888888888"];

}

-(void)query:(NSString*)phoneNumber{

// 设置我们之后解析XML时用的关键字,与响应报文中Body标签之间的getMobileCodeInfoResult标签对应
// 创建SOAP消息,内容格式就是网站上提示的请求报文的主体实体部分    这里使用了SOAP1.2;
NSString *soapMsg = [NSString stringWithFormat:
@"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<soap12:Envelope "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
"xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">"
"<soap12:Body>"
"<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"
"<mobileCode>%@</mobileCode>"
"<userID>%@</userID>"
"</getMobileCodeInfo>"
"</soap12:Body>"
"</soap12:Envelope>", phoneNumber, @""];

// 将这个XML字符串打印出来
//  NSLog(@"%@", soapMsg);
// 创建URL,内容是前面的请求报文报文中第二行主机地址加上第一行URL字段
NSURL *url = [NSURL URLWithString: @"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"];
// 根据上面的URL创建一个请求
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:@"%lu", (unsigned long)[soapMsg length]];
// 添加请求的详细信息,与请求报文前半部分的各字段对应
[req addValue:@"application/soap+xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
// 设置请求行方法为POST,与请求报文第一行对应
[req setHTTPMethod:@"POST"];
// 将SOAP消息加到请求中
[req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
// 创建连接

[NSURLConnection sendAsynchronousRequest:req queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {

if (!connectionError) {

NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"成功:%@",result);
}else{

NSLog(@"失败:%@",connectionError);
}

}];

}
@end
打印结果与上述1一样。

【3.使用XML请求SOAP,用NSURLSession实现】
目前苹果已经强烈推荐使用NSURLSession来进行网络请求了,虽然实现的代码量和难度 与NSURLConnection也差不多。实现代码如下:

#import "SOAP3ViewController.h"

@interface SOAP3ViewController ()

@property (strong, nonatomic) NSMutableData *webData;
@property (strong, nonatomic) NSURLConnection *conn;

@end

@implementation SOAP3ViewController

- (void)viewDidLoad {
[super viewDidLoad];

[self query:@"18888888888"];

}

-(void)query:(NSString*)phoneNumber{

// 设置我们之后解析XML时用的关键字,与响应报文中Body标签之间的getMobileCodeInfoResult标签对应
// 创建SOAP消息,内容格式就是网站上提示的请求报文的主体实体部分    这里使用了SOAP1.2;
NSString *soapMsg = [NSString stringWithFormat:
@"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<soap12:Envelope "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
"xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">"
"<soap12:Body>"
"<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"
"<mobileCode>%@</mobileCode>"
"<userID>%@</userID>"
"</getMobileCodeInfo>"
"</soap12:Body>"
"</soap12:Envelope>", phoneNumber, @""];

// 将这个XML字符串打印出来
//  NSLog(@"%@", soapMsg);
// 创建URL,内容是前面的请求报文报文中第二行主机地址加上第一行URL字段
NSURL *url = [NSURL URLWithString: @"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"];
// 根据上面的URL创建一个请求
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:@"%lu", (unsigned long)[soapMsg length]];
// 添加请求的详细信息,与请求报文前半部分的各字段对应
[req addValue:@"application/soap+xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
// 设置请求行方法为POST,与请求报文第一行对应
[req setHTTPMethod:@"POST"];
// 将SOAP消息加到请求中
[req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
// 创建连接

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

if (!error) {

NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"成功:%@",result);
}else{

NSLog(@"失败 : %@",error);
}

}];

[dataTask resume];

}

@end
打印结果与1相同。

【4.普通的Http请求,使用NSURLConnection】
最基本最普通的网络请求就是发送一个链接,链接里包含了需要发送的参数,同时请求方式可以是GET或者POST。这里我也是使用http://www.webxml.com.cn/zh_cn/web_services.aspx 进行号码归属地的请求。实现代码如下:

#import "HttpGet1ViewController.h"

@interface HttpGet1ViewController ()

@end

@implementation HttpGet1ViewController

- (void)viewDidLoad {
[super viewDidLoad];

/*
为什么要执行如下方法?
因为有的服务端要求把中文进行utf8编码,而我们的代码默认是unicode编码。必须要进行一下的转码,否则返回的可能为空,或者是其他编码格式的乱码了!
注意可以对整个url直接进行转码,而没必要对出现的每一个中文字符进行编码;
*/

//以下方法已经不推荐使用;
//  NSString *urlStr = [@"http://v.juhe.cn/weather/index?format=2&cityname=北京&key=88e194ce72b455563c3bed01d5f967c5"stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

//建议使用这个方法stringByAddingPercentEncodingWithAllowedCharacters,不推荐使用stringByAddingPercentEscapesUsingEncoding;
NSString *urlStr2 = [@"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo?mobileCode=18888888888&userId=" stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[self asynHttpGet:urlStr2];

}

- (NSString *)asynHttpGet:(NSString *)urlAsString{
NSURL *url = [NSURL URLWithString:urlAsString];
__block NSString *resault=@"";
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:30];
[urlRequest setHTTPMethod:@"GET"];

//以下方法已经被禁用;

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

[NSURLConnection
sendAsynchronousRequest:urlRequest
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {

if ([data length] >0  &&
error == nil){
NSString *html = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
resault=[html copy];

NSLog(@"返回的服务器数据 = %@", html);
}
else if ([data length] == 0 &&
error == nil){
resault=@"Nothing was downloaded.";
NSLog(@"Nothing was downloaded.");
}
else if (error != nil){
resault=[NSString stringWithFormat:@"Error happened = %@", error];
NSLog(@"发生错误 = %@", error);
}

}];

return resault;

}

@end


打印结果如下:



【5.普通的Http请求,使用NSURL Session】
NSURLSession是对NSURLConnection的改进与优化。这是对4的改进。实现代码如下:

#import "HttpGet2ViewController.h"

@interface HttpGet2ViewController ()

@end

@implementation HttpGet2ViewController

- (void)viewDidLoad {
[super viewDidLoad];

/*
为什么要执行如下方法?
因为有的服务端要求把中文进行utf8编码,而我们的代码默认是unicode编码。必须要进行一下的转码,否则返回的可能为空,或者是其他编码格式的乱码了!
注意可以对整个url直接进行转码,而没必要对出现的每一个中文字符进行编码;
*/

//以下方法已经不推荐使用;
//  NSString *urlStr = [@"http://v.juhe.cn/weather/index?format=2&cityname=北京&key=88e194ce72b455563c3bed01d5f967c5"stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

//建议使用这个方法stringByAddingPercentEncodingWithAllowedCharacters,不推荐使用stringByAddingPercentEscapesUsingEncoding;
NSString *urlStr2 = [@"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo?mobileCode=18888888888&userId=" stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[self asynHttpGet:urlStr2];

}

- (NSString *)asynHttpGet:(NSString *)urlAsString{
NSURL *url = [NSURL URLWithString:urlAsString];
//  __block NSString *resault=@"";
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:30];
[urlRequest setHTTPMethod:@"GET"];

//推荐使用这种请求方法;
NSURLSession *session = [NSURLSession sharedSession];

__block  NSString *result = @"";
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

if (!error) {
//没有错误,返回正确;
result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"返回正确:%@",result);

}else{
//出现错误;
NSLog(@"错误信息:%@",error);
}

}];

[dataTask resume];

return result;

}

@end


打印结果与4一样。

     总结,网络请求虽然代码看起来有点多,但还是比较简单的,也基本上是固定的,可以直接拿过来用。我将在下一篇博客中介绍使用AFNetworking来进行请求。

最近开源的iOS应用,高仿印象笔记  https://github.com/chenyufeng1991/iOS-Oncenote 。欢迎大家点赞并关注项目进度。也可以安装到手机上试玩哦。

github主页:https://github.com/chenyufeng1991  。欢迎大家访问!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: