iOS网络编程

一、使用NSURLConnection发送请求

NSURLConnection常见的发送请求方法有以下几种

  • 同步请求
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
  • 异步请求:根据对服务器返回数据的处理方式不同又可以分为两种
    • block回调
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
                          queue:(NSOperationQueue*) queue
              completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler
    • 代理:NSURLConnectionDataDelegate,在这种情况下需要调用start方法开始发送请求
/**
 *  请求错误(失败)的时候调用(请求超时、断网、没有网络,一般指客户端错误)
 */
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
/**
 *  当接收到服务器的响应(连通了服务器)就会调用
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
/**
 *  当接收到服务器的数据就会调用(可能会被调用多次,每次调用只会传递部分数据)
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
/**
 *  当服务器的数据接收完毕后就会调用
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

1. 发送GET请求

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     
 4     NSString *username = @"zhangsan";
 5     NSString *pwd = @"12345";
 6 
 7     // 发送请求GET给服务器
 8     // GET请求:请求行\请求头
 9     
10     // 1.设置请求路径
11     NSString *urlStr = [NSString stringWithFormat:@"http://localhost:8080/MJServer/login?username=%@&pwd=%@", username, pwd];
12     NSURL *url = [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
13     
14     // 2.创建请求对象(默认就是GET请求)
15     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
16     
17     // 3.发送请求(同步)
18 //    [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
19     
20     // 在队列中执行请求(可同步也可异步)
21     [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
22         // 服务器处理请求后返回的数据在这里进行解析,即解析data
23     }];
24 }

2. 发送POST请求

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     
 4     NSString *username = @"zhangsan";
 5     NSString *pwd = @"12345";
 6 
 7     // 发送请求POST给服务器
 8     // POST请求:请求体
 9     
10     // 1.设置请求路径
11     NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/login"];
12     
13     // 2.创建请求对象(默认就是GET请求)
14     NSURLRequest *request = [NSURLRequest requestWithURL:url];
15     // 设置请求超时
16     request.timeoutInterval = 5;
17     // 设置为POST请求
18     request.HTTPMethod = @"POST";
19     // 设置请求体
20     NSString *param = [NSString stringWithFormat:@"username=%@&pwd=%@", username, pwd];
21     request.HTTPBody = [param dataUsingEncoding:NSUTF8StringEncoding];
22     
23     // 通过请求头告诉服务器客户端的类型
24     [request setValue:@"iOS" forHTTPHeaderField:@"User-Agent"];
25     
26     
27     // 3.发送请求(同步)
28     // 在队列中执行请求(可同步也可异步)
29     [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
30         // 服务器处理请求后返回的数据在这里进行解析,即解析data
31     }];
32 }

二、大文件下载

小文件下载

  • 直接用NSData的+ (instancetype)dataWithContentsOfURL:(NSURL *)url;
  • 利用NSURLConnection发送一个HTTP请求去下载
  • 如果是下载图片,可以利用SDWebImage框架

1. 简单下载

@property (nonatomic, strong) NSFileHandle *writeHandle;


- (void)viewDidLoad {
    [super viewDidLoad];
    // 创建并发送请求
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/video.zip"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [NSURLConnection connectionWithRequest:request delegate:self];
}

#pragma mark - NSURLConnectionDataDelegate 代理方法
/**
 *  当接收到服务器的响应(连通了服务器)就会调用
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // 1.文件的存储路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [caches stringByAppendingPathComponent:@"video.zip"];
    
    // 2.创建一个空的文件到沙盒中
    NSFileManager *manager = [NSFileManager defaultManager];
    // 刚创建完毕的大小是0字节
    [manager createFileAtPath:filePath contents:nil attributes:nil];
    
    // 3.创建写数据的文件句柄
    self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
}

/**
 *  当接收到服务器的数据就会调用(可能会被调用多次,每次调用只会传递部分数据)
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // 移动到文件的尾部
    [self.writeHandle seekToEndOfFile];
    // 从当前移动的位置(文件尾部)开始写入数据
    [self.writeHandle writeData:data];
}

/**
 *  当服务器的数据接收完毕后就会调用
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // 关闭连接(不再输入数据到文件中)
    [self.writeHandle closeFile];
}

2. 暂停、恢复下载

思路:当暂停下载是请求就已经结束了,要恢复下载需要重新发送请求。可以在发送请求时设置请求头告诉服务器从哪里开始下载。

1     // 只下载前100个字节
2     [request setValue:@"bytes=0-99" forKey:@"Range"];

Range示例

bytes=0-99         从0到100的头100个字节

bytes=500-999   从500到999的第二个500租户额

bytes=500-        从500字节以后的所有字节

bytes=-500        最后的500字节

bytes=500-599,800-899   同时指定几个范围

 

三、NSURLCache缓存

一般只对GET请求进行缓存,不必对POST请求进行缓存。

NSURLCache的常见用法

  • 获得全局缓存对象(没必要手动创建)
NSURLCache *cache = [NSURLCache sharedURLCache];
  • 设置内存缓存的最大容量(单位是字节,默认为512KB)
@property NSUInteger memoryCapacity;
  • 设置硬盘缓存的最大容量(单位是字节,默认为10MB),硬盘缓存位置:沙盒/Library/Caches
@property NSUInteger diskCapacity;

只要设置了缓存策略,系统就会自动利用NSURLCache进行数据缓存

1     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
2     // 设置缓存策略
3     request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

iOS对NSURLRequest提供了7中缓存策略(实际上只有4中可用)

// 默认的缓存策略(取决于协议)
NSURLRequestUseProtocolCachePolicy = 0,
// 忽略缓存,重新请求
NSURLRequestReloadIgnoringLocalCacheData = 1,
//未实现(不可用)
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4,
// 忽略缓存,重新请求
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
// 有缓存就用缓存,没缓存就重新请求
NSURLRequestReturnCacheDataElseLoad = 2,
// 有缓存就用缓存,没有缓存就不发送请求,当做请求出错处理(离线模式)
NSURLRequestReturnCacheDataDontLoad = 3,
//未实现(不可用)
NSURLRequestReloadRevalidatingCacheData = 5,

缓存的相关操作

 1     NSURLCache *cache = [NSURLCache sharedURLCache];
 2     // 取得某个请求的缓存
 3     NSCachedURLResponse *response = [cache cachedResponseForRequest:request];
 4     if (response) {
 5         NSLog(@"这个请求已经存在缓存");
 6     }else {
 7         NSLog(@"这个请求没有缓存");
 8     }
 9     // 清除某个请求的缓存
10     [cache removeCachedResponseForRequest:request];
11     // 清除所有缓存
12     [cache removeAllCachedResponses];

四、检测网络状态

苹果官方提供了一个叫Reachability的示例程序,便于开发者检测网络状态

https://developer.apple.com/library/ios/samplecode/Reachability/Reachability.zip

将Reachability.h和Reachability.m拖放到项目中,并导入SystemConfiguration.framework即可使用Reachability。

 1     // 检测wifi状态
 2     Reachability *wifi = [Reachability reachabilityForLocalWiFi];
 3     if ([wifi currentReachabilityStatus] != NotReachable) {
 4         NSLog(@"有wifi");
 5     }else {
 6         NSLog(@"无wifi");
 7     }
 8     
 9     // 检测手机自带网络功能(能否上网)
10     Reachability *connection = [Reachability reachabilityForInternetConnection];
11     if ([connection currentReachabilityStatus] != NotReachable) {
12         NSLog(@"有网络");
13     }else {
14         NSLog(@"无网络");
15     }

较老版本的Reachability是使用非ARC编写的,需要在项目的Build Phases的Complie Sources修改Reachability.m文件的Complie Flags为-fno--objc-arc

 

五、使用AFNetworking发送请求

github地址:https://github.com/AFNetworking/AFNetworking

导入主头文件: #import "AFNetworking.h"

要使用AFN发送请求,需要先创建一个请求管理者

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

然后只需调用block即可发送HTTP请求

 1     /**
 2      *  发送GET请求
 3      *  @param GET: 请求地址
 4      *  @param parameters: 请求参数
 5      */
 6     [manager GET:@"" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
 7         // 请求成功时的回调
 8     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
 9         // 请求失败时的回调
10     }];
11     
12     /**
13      *  发送POST请求
14      *  @param POST: 请求地址
15      *  @param parameters: 请求参数
16      */
17     [manager POST:@"" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
18         // 请求成功时的回调
19     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
20         // 请求失败时的回调
21     }];

使用AFNetworking发送请求实例

下面以获取新浪OAuth授权的接口文档为例子。用AFN向新浪服务器发送请求

发送POST请求代码:

 1     // 创建请求管理类
 2     AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
 3     
 4     // 设置请求参数
 5     NSMutableDictionary *params = [NSMutableDictionary dictionary];
 6     params[@"client_id"] = @"2740450720";
 7     params[@"client_secret"] = @"717606369d8f7dcda59d78f4b25e8e30";
 8     params[@"grant_type"] = @"authorization_code";
 9     params[@"code"] = code;
10     params[@"redirect_uri"] = @"http://www.baidu.com";
11     
12     // 发送请求
13     [manager POST:@"https://api.weibo.com/oauth2/access_token" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
14         // 请求成功
15         NSString *accessToken = responseObject[@"access_token"];
16         NSLog(@"请求成功:%@ - %@", responseObject ,accessToken);
17     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
18         // 请求失败
19         NSLog(@"请求失败:%@", error);
20     }];
21     

发送GET请求和发送POST请求的操作步骤相同,只是调用的方法不同而已。同样将get请求的参数用一个字典装起来作为请求参数即可。

 

posted @ 2015-09-27 22:03  骑着蜗牛看雪  阅读(418)  评论(0编辑  收藏  举报