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

       在实际的项目开发中,连接网络是每一款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 ()

@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:
                       @""
                       ""
                       ""
                       ""
                       "%@"
                       "%@"
                       ""
                       ""
                       "", 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:
                       @""
                       ""
                       ""
                       ""
                       "%@"
                       "%@"
                       ""
                       ""
                       "", 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:
                       @""
                       ""
                       ""
                       ""
                       "%@"
                       "%@"
                       ""
                       ""
                       "", 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  。欢迎大家访问!



你可能感兴趣的:(iOS开发,iOS开发技术分享)