zoukankan      html  css  js  c++  java
  • 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请求的参数用一个字典装起来作为请求参数即可。

  • 相关阅读:
    vbox安装增强功能,实现宿主机文件夹共享并浏览器访问
    linux镜像下载
    linux命令之sed
    关于MySQL数据库的备份方案
    linux防火墙使用以及配置
    Jenkins安装部署(二)
    Jenkins安装部署(一)
    Centos7在虚拟机中扩展磁盘空间
    CentOS 7系统根目录分区扩容
    Linux下的SVN服务器搭建
  • 原文地址:https://www.cnblogs.com/JanaChen/p/4826459.html
Copyright © 2011-2022 走看看