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

iOS 【原生API NSURLConnection 网络请求】

2016-01-20 16:27 513 查看
//
//  ViewController.m
//  0713-04NSURLConnection-01
//
//  Created by 王中尧 on 16/7/13.
//  Copyright © 2016年 wzy. All rights reserved.
//

#import "ViewController.h"

@interface ViewController () <NSURLConnectionDataDelegate>

@property (nonatomic, strong) NSMutableData *resultData;

@end

@implementation ViewController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

//    [self networkSync];
//    [self networkAsync];
//    [self networkAsyncWithDelegate];
[self networkAsyncPost];
}

// 使用NSURLConnection同步请求(GET)
- (void)networkSync {
/*
使用NSURLConnection同步请求(GET)
发送网络请求的步骤:
(1)设置请求路径
(2)创建请求对象(默认是GET请求,且已经默认包含了请求头)
(3)使用NSURLSession sendsync方法发送网络请求
(4)接收到服务器的响应后,解析响应体
*/

// 1 确定请求路径
NSURL *url = [NSURL URLWithString:@"http://123.123.123.1/login?username=wzy&pwd=wzy&type=JSON"];

// 2 创建请求对象
// 该请求对象内部会默认提供请求头和请求体,请求方法默认GET
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];

// 3 使用NSURLConnection发送请求(GET)
// 拼接参数
NSURLResponse *response = nil;
NSError *error = nil;

// 发送请求
/*
第一个参数:请求对象
第二个参数:响应头信息
第三个参数:错误信息
*/
// 该方法是阻塞式的,会卡住线程
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

// 4 解析服务器返回的数据
NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}

// 使用NSURLConnection异步请求 (GET)
- (void)networkAsync {
/*
使用NSURLConnection异步请求(GET)
该方法不会卡住当前线程,网络请求任务是异步执行的
*/

// 1 确定请求路径
//    NSURL *url = [NSURL URLWithString:@"http://123.123.123.1/login?username=wzy&pwd=wzy&type=JSON"];
    NSString *urlStr = @"http://123.123.123.1/login2?username=wzy&pwd=wzy&type=JSON";
    // URL中文转码(当url中存在中文的时候一定要转码)
    urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:urlStr];

// 2 创建请求对象
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];

/*
第一个参数:请求对象
第二个参数:队列 决定block块在哪个线程中调用
第三个参数:completionHandler 完成(失败|成功)之后的回调
response:响应头信息
data:响应体信息
connectionError:错误信息
*/
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
// 解析响应体信息
NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// 解析响应头信息
NSLog(@"%@", response);
// 打印当前线程
NSLog(@"%@", [NSThread currentThread]);

// NSHTTPURLResponse 是响应头的真实类型
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
// 状态码
NSLog(@"%zd", res.statusCode);
// 响应报头
NSLog(@"%@", res.allHeaderFields);
}];

NSLog(@"___end___");

/*
打印结果:
2016-07-13 19:09:18.338 0713-04NSURLConnection-01[12881:1301919] ___end___
2016-07-13 19:09:18.394 0713-04NSURLConnection-01[12881:1301962] {"success":"登录成功"}   响应体信息
2016-07-13 19:09:18.394 0713-04NSURLConnection-01[12881:1301962] <NSHTTPURLResponse: 0x7fedf841f140> { URL: http://123.123.123.1/login?username=wzy&pwd=wzy&type=JSON } { status code: 200, headers {
"Content-Type" = "application/json;charset=UTF-8";
Date = "Wed, 13 Jul 2016 11:09:17 GMT";
Server = "Apache-Coyote/1.1";
"Transfer-Encoding" = Identity;
} }   响应头信息
2016-07-13 19:09:18.395 0713-04NSURLConnection-01[12881:1301962] <NSThread: 0x7fedf87321d0>{number = 3, name = (null)}   当前线程
2016-07-13 19:09:18.395 0713-04NSURLConnection-01[12881:1301962] 200   res.statusCode 状态码
2016-07-13 19:09:18.395 0713-04NSURLConnection-01[12881:1301962] {
"Content-Type" = "application/json;charset=UTF-8";
Date = "Wed, 13 Jul 2016 11:09:17 GMT";
Server = "Apache-Coyote/1.1";
"Transfer-Encoding" = Identity;
}   res.allHeaderFields 响应报头
*/
}

// 使用NSURLConnection异步请求(GET-代理)
- (void)networkAsyncWithDelegate {
/*
使用NSURLConnection异步请求(GET-代理)
步骤
(1)确定请求路径
(2)创建请求对象
(3)创建NSURLConnection对象并设置代理
(4)遵守NSURLConnectionDataDelegate协议,并实现相应的代理方法
(5)在代理方法中监听网络请求的响应
*/
NSURL *url = [NSURL URLWithString:@"http://123.123.123.1/login?username=wzy&pwd=wzy&type=JSON"];

NSURLRequest *request = [NSURLRequest requestWithURL:url];

// 设置代理方式一:(自动发送网络请求)
//    第一个参数:请求对象
//    第二个参数:谁成为NSURLConnetion对象的代理
// 注意:该方法内部虽然会把connection添加到runloop,但是如果当前的runloop不存在,那么不会主动创建
//    [[NSURLConnection alloc] initWithRequest:request delegate:self];

// 设置代理方式二:
//    第一个参数:请求对象
//    第二个参数:谁成为NSURLConnetion对象的代理
//    第三个参数:是否马上发送网络请求,如果该值为YES则立刻发送,如果为NO则不会发送网络请求
NSURLConnection *connect = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];

// start方法控制网络请求的发送
    // 注意:start方法内部会把当前的NSURLConnection对象作为一个source添加到当前线程对应的runloop中
    // 区别在于,如果调用start方法开启发送网络请求,那么再添加source的过程中,如果当前runloop不存在(一般来说子线程的runLoop需要手动创建)
    // 那么该方法内部会自动创建一个当前线程对应的runloop,并启动。
 [connect start];

// 可以调用cancel关闭请求(设置完这句话就不会有请求了,也不会调用代理方法)
//    [connect cancel];

// 设置代理方式三:
// 使用类方法设置代理,会自动发送网络请求(和方式一差不多)
//    NSURLConnection *connect = [NSURLConnection connectionWithRequest:request delegate:self];
}

// 使用NSURLConnection异步请求(POST)
- (void)networkAsyncPost {
/*
发送POST请求步骤
(1) 确定URL路径
(2) 创建请求对象(可变对象)
(3) 修改请求对象的方法为POST,设置请求体(Data)
(4) 发送一个异步请求
(5) 补充:设置请求超时,处理错误信息,设置请求头(如获取客户端的版本等等,请求头是可设置可不设置的)
*/
// 1 确定请求路径
NSURL *url = [NSURL URLWithString:@"http://123.123.123.1/login"];

// 2 创建 可变的 请求对象(因为还要对该请求对象配置属性)
// 默认的请求头 | 默认请求方法(GET)
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 2.1 设置请求方法为POST
request.HTTPMethod = @"POST";
// 2.2 设置参数(请求体)
request.HTTPBody = [@"username=wzy&pwd=wzy&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
// 2.3 设置请求超时时间;
request.timeoutInterval = 15; // 请求超时(如果在该时间段内没有完成请求就认为请求失败)
// 2.4 设置请求头
[request setValue:@"iOS 9.1" forHTTPHeaderField:@"User-Agent"];
//request addValue:<#(nonnull NSString *)#> forHTTPHeaderField:<#(nonnull NSString *)#>

// 3 发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if (connectionError) {
NSLog(@"请求失败-%@", connectionError);
}

// 4 解析服务器返回的数据
NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
}

#pragma mark - NSURLConnectionDataDelegate
// 1 接收到服务器响应的时候调用
// 第一个参数connection:监听的是哪个NSURLConnection对象
// 第二个参数response:接收到的服务器返回的响应头信息
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
self.resultData = [NSMutableData data];
NSLog(@"didReceiveResponse-接收到服务器响应");
}

// 2 接收到服务器返回的数据的时候调用 该方法可能会调用多次
// 第一个参数connection:监听的是哪个NSURLConnection对象
// 第二个参数data:本次接收到的服务端返回的二进制数据(可能是片段)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"didReceiveData-接收到服务器返回的数据");

// 拼接服务器返回的数据
[self.resultData appendData:data];
}

// 3 请求错误的时候调用(比如超时。一般网络加载的限定超时时间为15s或30s)
// 第一个参数connection:监听的是哪个NSURLConnection对象
// 第二个参数:网络请求的错误信息,如果请求失败,则error有值
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"connectionDidFinishLoading-请求错误-%@", error);
}

// 4 请求完成的时候调用
// 通常在该方法中解析服务器返回的数据
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"connectionDidFinishLoading-请求完成");

// 解析服务器返回的数据
NSLog(@"%@", [[NSString alloc] initWithData:self.resultData encoding:NSUTF8StringEncoding]);
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息