AFNetworking 网络请求

前言

  • 在 iOS 开发中,一般情况下,简单的向某个 Web 站点简单的页面提交请求并获取服务器的响应,用 Xcode 自带的 NSURLConnection 是能胜任的。但是,在绝大部分下我们所需要访问的 Web 页面则是属于那种受到权限保护的页面,并不是有一个简单的 URL 可以访问的。这就涉及到了 Session 和 Cookie 的处理了,在此时使用 NSURLConnection 也是能够达到要求的,只是其中处理起来的复杂度和难度就提升了。为了更好的处理向 Web 站点的请求,包括处理 Session,Cookie 等细节问题,使用 AFNetworking 则是更好的选择。

    • 1) Session:中文有译作时域的,就是指某个客户端从访问服务器起到停止访问这一段的时间间隔被称为时域。
    • 2) Cookie:由服务器发送给客户端,把 Cookie 的 key:value 值储存在本地文件夹下,当下次请求的时候能够直接发送 Cookie 获得权限验证。

1、AFNetworking

1.1 AFNetworking 特点

  • AFNetworking 是一个讨人喜欢的网络库,适用于 iOS,Mac OS X 以及 Watch OS。
  • AFNetworking 构建在 NSURLSession,NSOperation,以及其他熟悉的 Foundation 技术之上。它拥有良好的架构,丰富的 API,以及模块化构建方式,使得使用起来非常轻松。
  • AFNetworking 可以用于发送 HTTP 请求,接收 HTTP 的响应,但是不会缓存服务器的响应,不能执行 HTML 页面中的 JAvascript 代码。
  • AFNetworking 内置支持 JSON,Plist 文件和 XML 文件的半自动序列化和反序列化,可以对 JSON 格式的请求响应数据自动做反序列化,XML 格式数据需要手动反序列化,使用比较方便。
  • AFNetworking 中回调函数将在主线程中进行,程序员不需要关心线程间通讯问题。
  • AFNetworking 具有完善的错误处理机制。

1.2 AFNetworking 官方使用建议

  • 建立 AFHTTPSesssionManager 的单例子类,统一管理全局的所有网络访问。

    • NetworkTools.h

      1
      2
      3
      4
      5
      6
      7
      #import <AFNetworking/AFNetworking.h>

      @interface NetworkTools : AFHTTPSessionManager

      + (instancetype)sharedNetworkTools;

      @end
    • NetworkTools.m

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      @implementation NetworkTools

      + (instancetype)sharedNetworkTools {
      static NetworkTools *tools;

      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{

      // baseURL 的目的,就是让后续的网络访问直接使用 相对路径即可,baseURL 的路径一定要有 / 结尾
      NSURL *baseURL = [NSURL URLWithString:@"http://c.m.163.com/"];

      NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

      tools = [[self alloc] initWithBaseURL:baseURL sessionConfiguration:config];

      // 修改 解析数据格式 能够接受的内容类型 - 官方推荐的做法,民间做法:直接修改 AFN 的源代码
      tools.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",
      @"text/json",
      @"text/javascript",
      @"text/html",
      nil];
      });
      return tools;
      }

      @end

1.3 AFNetworking 系统需求

AFNetworking Version Minimum iOS Target Target Notes
3.x iOS 7 Xcode 7+ is required. NSURLConnectionOperation support has been removed.
2.6 -> 2.6.3 iOS 7 Xcode 7+ is required.
2.0 -> 2.5.4 iOS 6 Xcode 5+ is required. NSURLSession subspec requires iOS 7 or OS X 10.9.
1.x iOS 5
0.10.x iOS 4

1.4 AFNetworking 框架结构

  • 1) V 2.5.4:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    NSURLConnectionNSURLConnection 网络请求的封装(iOS 9.0 DEPRECATED)

    AFURLConnectionOperation
    AFHTTPRequestOperation
    AFHTTPRequestOperationManager

    NSURLSessionNSURLSession 网络请求的封装(iOS 7.0 AVAILABLE

    AFURLSessionManager
    AFHTTPSessionManager

    Serialization 序列化 & 反序列化 格式

    <AFURLRequestSerialization> 发送给服务器的数据格式(序列化)
    AFHTTPRequestSerializer 二进制 默认
    AFJSONRequestSerializer JSON POST JSON
    AFPropertyListRequestSerializer Plist 苹果专有,极少用

    <AFURLResponseSerialization> 从服务器接收的数据格式(反序列化)
    AFHTTPResponseSerializer 二进制
    AFJSONResponseSerializer JSON 默认
    AFXMLParserResponseSerializer XMLParser SAX 解析
    AFXMLDocumentResponseSerializer (Mac OS X) XMLDocument DOM 解析
    AFPropertyListResponseSerializer Plist 苹果专有,极少用
    AFImageResponseSerializer Image 图片
    AFCompoundResponseSerializer Compound 组合的

    Additional Functionality 辅助功能

    AFSecurityPolicy 安全策略
    AFNetworkReachabilityManager 网络状态监测

    UIKit+AFNetworking AFNetworking 为相应的 UIKit 控件添加的分类。
  • 2) V 3.1.0:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    NSURLSessionNSURLSession 网络请求的封装(iOS 7.0 AVAILABLE

    AFURLSessionManager
    AFHTTPSessionManager

    Serialization 序列化 & 反序列化 格式

    <AFURLRequestSerialization> 发送给服务器的数据格式(序列化)
    AFHTTPRequestSerializer 二进制 默认
    AFJSONRequestSerializer JSON POST JSON
    AFPropertyListRequestSerializer Plist 苹果专有,极少用

    <AFURLResponseSerialization> 从服务器接收的数据格式(反序列化)
    AFHTTPResponseSerializer 二进制
    AFJSONResponseSerializer JSON 默认
    AFXMLParserResponseSerializer XMLParser SAX 解析
    AFXMLDocumentResponseSerializer (Mac OS X) XMLDocument DOM 解析
    AFPropertyListResponseSerializer Plist 苹果专有,极少用
    AFImageResponseSerializer Image 图片
    AFCompoundResponseSerializer Compound 组合的

    Additional Functionality 辅助功能

    AFSecurityPolicy 安全策略
    AFNetworkReachabilityManager 网络状态监测

    UIKit+AFNetworking AFNetworking 为相应的 UIKit 控件添加的分类。
  • 3)NSURLConnection 网络请求封装:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    iOS 9.0 DEPRECATED

    1> AFHTTPRequestOperationManager:

    属性:
    requestSerializer :设置请求的数据格式
    responseSerializer :设置响应的数据格式

    reachabilityManager :网络连接状态管理器,监控网络连接状态

    方法:
    HTTPRequestOperationWithRequest:如果需要在请求中设置额外的属性,例如:身份验证,提前准备好 request ,调用此方法就可以了

    manager :实例化 HTTP Reuqest 管理器

    GET :GET 请求
    HEAD :HEAD 请求
    POST :POST 请求,constructingBodyWithBlock:POST 上传文件用的
    PUT :PUT 请求
    PATCH :PATCH 请求,RESTFul 的一个方法,极少用
    DELETE :DELETE 请求

    所有的方法:参数字典
    成功回调
    失败回调
    URL 都是使用字符串来传递的
  • 4) NSURLSession 网络请求封装:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    iOS 7.0 AVAILABLE

    1> 说明:

    基于指定的 NSURLSessionConfiguration 创建并管理一个 NSURLSession 对象。
    遵守 NSURLSessionTaskDelegateNSURLSessionDataDelegateNSURLSessionDownloadDelegateNSURLSessionDelegate 协议。

    2> 初始化:

    初始化 :- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration
    取消 :- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks;

    3> 任务:

    数据任务:dataTaskWithRequest:

    上传任务:
    从文件上传 :uploadTaskWithRequest:fromFile:
    从数据上传 :uploadTaskWithRequest:fromData:
    从数据流上传 :uploadTaskWithStreamedRequest:

    下载任务:
    使用指定的请求创建下载任务 :downloadTaskWithRequest:
    使用续传数据创建下载任务 :downloadTaskWithResumeData:

    任务进度:
    上传进度:- (NSProgress *)uploadProgressForTask:(NSURLSessionUploadTask *)uploadTask;
    下载进度:- (NSProgress *)downloadProgressForTask:(NSURLSessionDownloadTask *)downloadTask;

    4> 代理回调:

    <1> 会话代理回调:

    设置管理的会话无效回调方法:

    - (void)setSessionDidBecomeInvalidBlock:(void (^)(NSURLSession *session, NSError *error))block;

    block 参数:
    session :会话
    error :导致会话无效相关的错误

    设置当管理的会话无效时执行的 block。

    设置需要身份验证回调方法:

    - (void)setSessionDidReceiveAuthenticationChallengeBlock:
    (NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session,
    NSURLAuthenticationChallenge *challenge,
    NSURLCredential * __autoreleasing *credential))block;

    block 参数:
    session :会话
    challenge :身份验证质询
    credential :指向凭据的指针,该凭据用于解决身份验证

    block 返回值:
    返回身份验证的配置情况

    设置当连接需要身份验证质询时执行的 block。

    <2> 任务代理回调:

    设置上传流回调方法:

    - (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block;

    block 返回值:
    要上传文件的 NSInputStream

    设置一个请求体二进制流发送至远程服务器时执行的 block。

    设置重定向回调方法:

    - (void)setTaskWillPerformHTTPRedirectionBlock:(NSURLRequest * (^)(NSURLSession *session,
    NSURLSessionTask *task,
    NSURLResponse *response,
    NSURLRequest *request))block;

    block 参数:
    session :会话
    task :任务
    response :重定向响应
    request :要重定向的请求

    block 返回值:
    返回导致重定向的请求 NSURLRequest

    设置 HTTP 请求尝试重定向到其他 URL 时执行的 block。

    设置身份验证质询回调方法:

    - (void)setTaskDidReceiveAuthenticationChallengeBlock:
    (NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session,
    NSURLSessionTask *task,
    NSURLAuthenticationChallenge *challenge,
    NSURLCredential * __autoreleasing *credential))block;

    block 参数:
    session :会话
    task :任务
    challenge :身份验证质询
    credential :指向解决验证需要使用凭据的指针

    block 返回值:
    返回对身份验证请求质询的处置

    设置接收到特定身份验证质询时执行的 block。

    设置上传进度回调方法:

    - (void)setTaskDidSendBodyDataBlock:(void (^)(NSURLSession *session,
    NSURLSessionTask *task,
    int64_t bytesSent,
    int64_t totalBytesSent,
    int64_t totalBytesExpectedToSend))block;

    block 参数:
    session :会话
    task :任务
    bytesSent :本次上传字节数
    totalBytesSent :已经上传的字节数
    totalBytesExpectedToSend :总字节数

    设置跟踪上传进度要执行的 block。

    设置任务完成回调方法:

    - (void)setTaskDidCompleteBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, NSError *error))block;

    block 参数:
    session :会话
    task :任务
    error :任务执行过程中出现的错误

    设置特定任务完成后执行的 block。

    <3> 数据任务代理回调:

    设置接收到响应回调方法:

    - (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session,
    NSURLSessionDataTask *dataTask,
    NSURLResponse *response))block;

    block 参数:
    session :会话
    dataTask :任务
    response :接收到的响应

    block 返回值:
    返回对会话响应的处置

    设置数据任务接收到响应时执行的 block。

    设置成为下载任务回调方法:

    - (void)setDataTaskDidBecomeDownloadTaskBlock:(void (^)(NSURLSession *session,
    NSURLSessionDataTask *dataTask,
    NSURLSessionDownloadTask *downloadTask))block;

    block 参数:
    session :会话
    dataTask :任务
    downloadTask :成为的下载任务

    设置数据任务成为下载任务时执行的 block。

    设置接收到数据回调方法:

    - (void)setDataTaskDidReceiveDataBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block;

    block 参数:
    session :会话
    dataTask :任务
    data :接收的数据

    设置数据任务接收到数据时执行的 block。

    设置缓存行为回调方法:

    - (void)setDataTaskWillCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLSession *session,
    NSURLSessionDataTask *dataTask,
    NSCachedURLResponse *proposedResponse))block;

    block 参数:
    session :会话
    dataTask :任务
    proposedResponse :建议缓存的 URL 响应

    block 返回值:
    返回要缓存的响应

    设置确定数据任务的缓存行为执行的 block。

    设置入队消息提交回调方法:

    - (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block;

    block 参数:
    session:会话

    设置会话的所有入队消息已经被提交时执行一次的 block。

    <4> 下载任务代理回调:

    设置下载完成回调方法:

    - (void)setDownloadTaskDidFinishDownloadingBlock:(NSURL * (^)(NSURLSession *session,
    NSURLSessionDownloadTask *downloadTask,
    NSURL *location))block;

    block 参数:
    session :会话
    downloadTask :下载任务
    location :保存下载文件的临时位置

    block 返回值:
    下载文件被移动到的 URL

    设置下载任务完成后执行的 block。

    设置下载进度回调方法:

    - (void)setDownloadTaskDidWriteDataBlock:(void (^)(NSURLSession *session,
    NSURLSessionDownloadTask *downloadTask,
    int64_t bytesWritten,
    int64_t totalBytesWritten,
    int64_t totalBytesExpectedToWrite))block;

    block 参数:
    session :会话
    downloadTask :下载任务
    bytesWritten :本次下载字节数
    totalBytesWritten :已经下载的字节数
    totalBytesExpectedToWrite :总下载字节数

    设置跟踪下载进度重复执行的 block,该 block 可能会被调用多次,并在会话管理器操作队列中执行。

    设置下载续传回调方法:

    - (void)setDownloadTaskDidResumeBlock:(void (^)(NSURLSession *session,
    NSURLSessionDownloadTask *downloadTask,
    int64_t fileOffset,
    int64_t expectedTotalBytes))block;

    block 参数:
    session :会话
    downloadTask :下载任务
    fileOffset :续传下载的文件偏移位置
    expectedTotalBytes :总下载字节数

    设置下载任务续传时执行的 blok。

    5> 通知:

    <1> 通知:
    AFNetworkingTaskDidResumeNotification :任务继续通知
    AFNetworkingTaskDidCompleteNotification :任务结束执行通知
    AFNetworkingTaskDidSuspendNotification :任务暂停执行通知
    AFURLSessionDidInvalidateNotification :网络会话无效通知
    AFURLSessionDownloadTaskDidFailToMoveFileNotification :会话的下载任务将临时下载文件移动指定目录发生错误通知

    <2> 通知键值:
    AFNetworkingTaskDidCompleteResponseDataKey :任务的原始响应数据
    AFNetworkingTaskDidCompleteSerializedResponseKey :任务响应数据的反序列化对象
    AFNetworkingTaskDidCompleteResponseSerializerKey :响应序列化器用于反序列化响应数据
    AFNetworkingTaskDidCompleteAssetPathKey :与下载任务关联的文件路径
    AFNetworkingTaskDidCompleteErrorKey :与任务或者响应反序列化关联的错误
  • 5) AFNetworking 常用数据格式组合设置:

    • AFN 内置支持 JSON,Plist 文件和 XML 文件的半自动序列化和反序列化,可以对 JSON 格式的请求响应数据自动做反序列化,XML 格式数据需要手动反序列化,使用比较方便。AFN 在反序列化数据之前,会判断服务器返回的 content-Type,如果 content-Type 不符合要求,就放弃反序列化。

    • AFN 默认可以接收的类型:

      • application/json
      • text/json
      • text/javascript
    • 1> 发送二进制数据,接收 JSON,最常用的网络数据格式组合:

      • 发送数据:
        • 二进制数据:AFHTTPRequestSerializer(默认)
      • 接收数据:
        • JSON 数据:AFJSONResponseSerializer(默认)
    • 2> 发送二进制数据,接收 XML:

      • 发送数据:
        • 二进制数据:AFHTTPRequestSerializer(默认)
      • 接收数据:
        • XML SAX 解析:AFXMLParserResponseSerializer
        • XML DOM 解析:AFHTTPResponseSerializer
    • 3> 发送二进制数据,接收二进制数据(下载…):

      • 发送数据:
        • 二进制数据:AFHTTPRequestSerializer(默认)
      • 接收数据:
        • 二进制数据:AFHTTPResponseSerializer
    • 4> 发送 JSON 数据,接收 JSON:

      • 发送数据:
        • JSON 数据:AFJSONRequestSerializer
      • 接收数据:
        • JSON 数据:AFJSONResponseSerializer(默认)
    • 5> 接收 图像:

      • 基本上都使用 SDWebImage,缓存做的比 AFN 的要好一些
  • 6) AFSecurityPolicy 安全策略:

    • NSURLConnection 已经封装了 https 连接的建立、数据的加密解密功能,我们直接使用 NSURLConnection 是可以访问 https 网站的,但 NSURLConnection 并没有验证证书是否合法,无法避免中间人攻击。要做到真正安全通讯,需要我们手动去验证服务端返回的证书,AFNetworking 中 AFSecurityPolicy 封装了证书验证的过程,让用户可以轻易使用,除了去系统信任 CA 机构列表验证,还支持 SSL Pinning 方式的验证。

    • 1> AFSecurityPolicy 安全策略模式:

      • AFSSLPinningModeNone:

        • 这个模式表示不做 SSL pinning,只跟浏览器一样在系统的信任机构列表里验证服务端返回的证书。若证书是信任机构签发的就会通过,若是自己服务器生成的证书,这里是不会通过的。
      • AFSSLPinningModeCertificate:

        • 这个模式表示用证书绑定方式验证证书,需要客户端保存有服务端的证书拷贝,这里验证分两步,第一步验证证书的域名/有效期等信息,第二步是对比服务端返回的证书跟客户端返回的是否一致。
      • AFSSLPinningModePublicKey:

        • 这个模式同样是用证书绑定方式验证,客户端要有服务端的证书拷贝,只是验证时只验证证书里的公钥,不验证证书的有效期等信息。只要公钥是正确的,就能保证通信不会被窃听,因为中间人没有私钥,无法解开通过公钥加密的数据。
    • 2> HTTPS:

      • 代理方法:

        1
        2
        3
        - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge 
        completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition,
        NSURLCredential *))completionHandler
        • 参数:

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          NSURLAuthenticationChallenge:身份验证质询

          protectionSpace:保护空间,在信任受保护空间中的凭据之前,无法继续后续的网络请求。

          NSURLSessionAuthChallengeDisposition:对凭据的处置

          NSURLSessionAuthChallengeUseCredential :使用指定的凭据。
          NSURLSessionAuthChallengePerformDefaultHandling :默认处理,凭据参数会被忽略。
          NSURLSessionAuthChallengeCancelAuthenticationChallenge :整个请求将被忽略。
          NSURLSessionAuthChallengeRejectProtectionSpace :拒绝本次凭据,尝试下一次验证保护空间。
        • 代码:

          1
          2
          3
          4
          5
          6
          if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

          NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

          completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
          }
  • 7) AFNetworkReachabilityManager 网络状态监测:

    • 状态:

      1
      2
      3
      4
      AFNetworkReachabilityStatusUnknown          = -1,               网络状态未知
      AFNetworkReachabilityStatusNotReachable = 0, 无网络连接
      AFNetworkReachabilityStatusReachableViaWWAN = 1, 无线网络(蜂窝移动网络)
      AFNetworkReachabilityStatusReachableViaWiFi = 2, WiFi 网络
    • 属性:

      1
      2
      3
      4
      5
      networkReachabilityStatus                                       获取网络连接状态

      isReachable; 网络是否连接
      isReachableViaWiFi; WiFi 是否连接
      isReachableViaWWAN; 蜂窝网络 是否连接
    • 方法:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      + (instancetype)sharedManager;                                  实例化网络状态监测管理器
      + (instancetype)managerForDomain:(NSString *)domain; 实例化 相对于某个域名 网络状态监测管理器
      + (instancetype)managerForAddress:(const void *)address; 实例化 相对于某个地址 网络状态监测管理器

      - (void)startMonitoring; 开启监听网络状态
      - (void)stopMonitoring; 关闭网络状态监听

      - (NSString *)localizedNetworkReachabilityStatusString; 获取本地化网络状态字符串

      AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); 转换网络状态为字符串格式

      - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block; 网络状态改变回调
    • 通知:

      1
      2
      AFNetworkingReachabilityDidChangeNotification                   网络状态改变通知
      AFNetworkingReachabilityNotificationStatusItem 网络状态项

2、AFNetworking 的添加

3、AFNetworking 的设置

  • Objective-C

    • Manager 的创建

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      // AFHTTPSessionManager

      AFHTTPSessionManager *manager1 = [AFHTTPSessionManager manager];

      NSURL *baseURL2 = [NSURL URLWithString:@"http://192.168.88.200"];
      AFHTTPSessionManager *manager2 = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL2];

      NSURL *baseURL3 = [NSURL URLWithString:@"http://192.168.88.200"];
      NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
      AFHTTPSessionManager *manager3 = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL3 sessionConfiguration:config];

      // AFURLSessionManager

      AFURLSessionManager *manager4 = [[AFURLSessionManager alloc]
      initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

      // 取消挂起的 task
      [[AFURLSessionManager alloc] invalidateSessionCancelingTasks:YES];
    • URLRequest 的创建

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      NSURL *url1 = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video?type=JSON"];
      NSURL *url2 = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video"];

      NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video";
      NSDictionary *params = @{@"type":@"JSON"};

      // GET 创建方式

      NSURLRequest *request1 = [NSURLRequest requestWithURL:url1];

      NSURLRequest *request2 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET"
      URLString:urlStr
      parameters:params
      error:NULL];

      // POST 创建方式

      NSMutableURLRequest *request3 = [NSMutableURLRequest requestWithURL:url2];
      request3.HTTPMethod = @"POST";
      request3.HTTPBody = [@"type=JSON" dataUsingEncoding:NSUTF8StringEncoding];

      NSURLRequest *request4 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST"
      URLString:urlStr
      parameters:params
      error:NULL];

      NSURLRequest *request5 = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST"
      URLString:urlStr
      parameters:params
      constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {

      } error: NULL];
    • Request 的设置

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video?type=JSON"]];

      // 设置参数编码方式
      /*
      `NSUTF8StringEncoding` by default
      */
      manager.requestSerializer.stringEncoding = NSUTF8StringEncoding;

      // 设置缓存策略
      /*
      `NSURLRequestUseProtocolCachePolicy` by default.
      */
      manager.requestSerializer.cachePolicy = NSURLRequestUseProtocolCachePolicy;

      request.cachePolicy = NSURLRequestUseProtocolCachePolicy;

      // 设置网络服务类型
      /*
      `NSURLNetworkServiceTypeDefault` by default.
      */
      manager.requestSerializer.networkServiceType = NSURLNetworkServiceTypeDefault;

      request.networkServiceType = NSURLNetworkServiceTypeDefault;

      // 设置请求超时时间
      /*
      The default timeout interval is 60 seconds.
      */
      manager.requestSerializer.timeoutInterval = 15;

      request.timeoutInterval = 15;

      // 是否允许蜂窝网络访问
      /*
      `YES` by default.
      */
      manager.requestSerializer.allowsCellularAccess = YES;

      request.allowsCellularAccess = YES;

      // 设置是否应用默认的 Cookies
      /*
      `YES` by default.
      */
      manager.requestSerializer.HTTPShouldHandleCookies = YES;

      request.HTTPShouldHandleCookies = YES;

      // 设置是否使用 Pipelining
      /*
      `NO` by default.
      */
      manager.requestSerializer.HTTPShouldUsePipelining = NO;

      request.HTTPShouldUsePipelining = NO;

      // 请求头设置

      [manager.requestSerializer setValue:@"iPhone" forHTTPHeaderField:@"User-Agent"];

      [request setValue:@"iPhone" forHTTPHeaderField:@"User-Agent"];

      // 设置用户验证

      [manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"admin" password:@"adminpasswd"];

      NSString *username = @"admin";
      NSString *password = @"adminpasswd";
      NSString *userPasswordString = [NSString stringWithFormat:@"%@:%@", username, password];
      NSData *userPasswordData = [userPasswordString dataUsingEncoding:NSUTF8StringEncoding];
      NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];
      NSString *authString = [NSString stringWithFormat:@"Basic: %@", base64EncodedCredential];

      [request setValue:authString forHTTPHeaderField:@"Authorization"];

      // 清除用户验证信息

      [manager.requestSerializer clearAuthorizationHeader];

      [request setValue:nil forHTTPHeaderField:@"Authorization"];

      // 设置请求体
      request.HTTPBody = [@"type=JSON" dataUsingEncoding:NSUTF8StringEncoding];

      // 设置请求模式

      // 单独设置
      /*
      默认是 GET
      */
      request.HTTPMethod = @"POST";

      // 直接设置

      NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video";
      NSDictionary *parameters = @{@"type":@"XML"};

      NSURLRequest *request1 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST"
      URLString:urlStr
      parameters:parameters
      error:NULL];
    • 设置数据请求格式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      NSString *urlStr = @"http://example.com";
      NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]};

      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

      // 二进制 格式

      // POST http://example.com/
      // Content-Type: application/x-www-form-urlencoded

      // foo=bar&baz[]=1&baz[]=2&baz[]=3

      manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // 默认

      NSURLRequest *request1 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST"
      URLString:urlStr
      parameters:parameters
      error:NULL];

      // JSON 格式

      // POST http://example.com/
      // Content-Type: application/json

      // {"foo": "bar", "baz": [1,2,3]}

      manager.requestSerializer = [AFJSONRequestSerializer serializer];

      NSURLRequest *request2 = [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST"
      URLString:urlStr
      parameters:parameters
      error:NULL];

      // Plist 格式

      manager.requestSerializer = [AFPropertyListRequestSerializer serializer];

      NSURLRequest *request3 = [[AFPropertyListRequestSerializer serializer] requestWithMethod:@"POST"
      URLString:urlStr
      parameters:parameters
      error:NULL];
    • 设置数据响应格式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

      AFURLSessionManager *manager1 = [[AFURLSessionManager alloc]
      initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

      // 二进制
      manager.responseSerializer = [AFHTTPResponseSerializer serializer];

      // JSON,默认,application/json, text/json, text/javascript
      manager.responseSerializer = [AFJSONResponseSerializer serializer];

      // XMLParser,SAX 解析
      manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

      // Plist
      manager.responseSerializer = [AFPropertyListResponseSerializer serializer];

      // Image
      manager.responseSerializer = [AFImageResponseSerializer serializer];

      // Compound
      manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    • AFHTTPSessionManager 请求

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      // GET

      // DEPRECATED_ATTRIBUTE
      - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
      parameters:(nullable id)parameters
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
      parameters:(nullable id)parameters
      progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      // HEAD

      - (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString
      parameters:(nullable id)parameters
      success:(nullable void (^)(NSURLSessionDataTask *task))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      // POST

      // DEPRECATED_ATTRIBUTE
      - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
      parameters:(nullable id)parameters
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
      parameters:(nullable id)parameters
      progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      // DEPRECATED_ATTRIBUTE
      - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
      parameters:(nullable id)parameters
      constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
      parameters:(nullable id)parameters
      constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
      progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      // PUT

      - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString
      parameters:(nullable id)parameters
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      // PATCH

      - (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString
      parameters:(nullable id)parameters
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

      // DELETE

      - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString
      parameters:(nullable id)parameters
      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    • AFURLSessionManager 请求

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      // Data Tasks

      - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
      completionHandler:(nullable void (^)(NSURLResponse *response,
      id _Nullable responseObject,
      NSError * _Nullable error))completionHandler;

      - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
      uploadProgress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
      downloadProgress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
      completionHandler:(nullable void (^)(NSURLResponse *response,
      id _Nullable responseObject,
      NSError * _Nullable error))completionHandler;

      // Upload Tasks

      - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
      fromFile:(NSURL *)fileURL
      progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
      completionHandler:(nullable void (^)(NSURLResponse *response,
      id _Nullable responseObject,
      NSError * _Nullable error))completionHandler;

      - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
      fromData:(nullable NSData *)bodyData
      progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
      completionHandler:(nullable void (^)(NSURLResponse *response,
      id _Nullable responseObject,
      NSError * _Nullable error))completionHandler;

      - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
      progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
      completionHandler:(nullable void (^)(NSURLResponse *response,
      id _Nullable responseObject,
      NSError * _Nullable error))completionHandler;

      // Download Tasks

      - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
      progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
      destination:(nullable NSURL * (^)(NSURL *targetPath,
      NSURLResponse *response))destination
      completionHandler:(nullable void (^)(NSURLResponse *response,
      NSURL * _Nullable filePath,
      NSError * _Nullable error))completionHandler;

      - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
      progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
      destination:(nullable NSURL * (^)(NSURL *targetPath,
      NSURLResponse *response))destination
      completionHandler:(nullable void (^)(NSURLResponse *response,
      NSURL * _Nullable filePath,
      NSError * _Nullable error))completionHandler;

4、AFNetworking 网络状态监测

  • Objective-C

    • 网络连接状态:

      1
      2
      3
      4
      AFNetworkReachabilityStatusUnknown          = -1,               网络状态未知
      AFNetworkReachabilityStatusNotReachable = 0, 无网络连接
      AFNetworkReachabilityStatusReachableViaWWAN = 1, 无线网络(蜂窝移动网络)
      AFNetworkReachabilityStatusReachableViaWiFi = 2, WiFi 网络
    • 由于检测网络有一定的延迟,如果启动 App 立即去检测调用 [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus 有可能得到的是 netStatus == AFNetworkReachabilityStatusUnknown; 但是此时明明是有网的,建议在收到监听网络状态回调以后再取 [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus。或者延时调用 [self performSelector:@selector(networkReachability:) withObject:nil afterDelay:0.35f];。

    • 必须开启监听,才能获得网络状态。

      • AFNetworkReachabilityManager 方式

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        // 开启监听网络状态
        [[AFNetworkReachabilityManager sharedManager] startMonitoring];

        // 关闭网络状态监听
        [[AFNetworkReachabilityManager sharedManager] stopMonitoring];

        // 监听网络状态回调
        [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {

        // 开启网络状态监听后,只要网络状态发生改变就会调用该 Block 代码段
        }];

        // 判断网络是否连接
        BOOL isReachable = [AFNetworkReachabilityManager sharedManager].isReachable;

        // 判断 WiFi 是否连接
        BOOL isReachableViaWiFi = [AFNetworkReachabilityManager sharedManager].isReachableViaWiFi;

        // 判断 无线网络 是否连接
        BOOL isReachableViaWWAN = [AFNetworkReachabilityManager sharedManager].isReachableViaWWAN;

        // 获取网络连接状态
        AFNetworkReachabilityStatus netStatus = [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus;

        // 转换网络状态为字符串格式
        NSString *netStatusStr1 = AFStringFromNetworkReachabilityStatus(netStatus);

        // 获取网络连接状态
        NSString *netStatusStr2 = [[AFNetworkReachabilityManager sharedManager] localizedNetworkReachabilityStatusString];
      • AFHTTPSessionManager/AFURLSessionManager 方式

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

        AFURLSessionManager * manager = [[AFURLSessionManager alloc]
        initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

        // 开启监听网络状态
        [manager.reachabilityManager startMonitoring];

        NSOperationQueue *operationQueue = manager.operationQueue;

        [manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {

        // 开启网络状态监听后,只要网络状态发生改变就回调用该 Block 代码段

        NSString *netStatus = AFStringFromNetworkReachabilityStatus(status);
        NSLog(@"Reachability: %@", netStatus);

        switch (status) {
        case AFNetworkReachabilityStatusReachableViaWWAN:
        case AFNetworkReachabilityStatusReachableViaWiFi:

        // 继续 queue
        [operationQueue setSuspended:NO];
        break;

        case AFNetworkReachabilityStatusNotReachable:
        default:

        // 暂停 queue
        [operationQueue setSuspended:YES];
        break;
        }
        }];

5、AFNetworking 安全策略设置

  • Objective-C

    • AFSecurityPolicy 方式

      1
      2
      3
      4
      5
      6
      7
      AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];

      // 设置是否信任无效或过期的 SSL 证书的服务器。默认为否
      securityPolicy.allowInvalidCertificates = YES;

      // 设置安全验证模式,默认为 AFSSLPinningModeNone
      securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
    • AFHTTPSessionManager/AFURLSessionManager 方式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

      AFURLSessionManager * manager = [[AFURLSessionManager alloc]
      initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

      // 设置是否信任无效或过期的 SSL 证书的服务器。默认为否
      manager.securityPolicy.allowInvalidCertificates = YES;

      // 设置安全验证模式,默认为 AFSSLPinningModeNone
      manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];

6、AFHTTPRequestOperationManager 的使用

  • Objective-C

    • Manager 的创建

      1
      2
      3
      4
      5
      NSURL *baseURL = [NSURL URLWithString:@"http://192.168.88.200"];

      AFHTTPRequestOperationManager *manager1 = [AFHTTPRequestOperationManager manager];

      AFHTTPRequestOperationManager *manager2 = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
    • 设置数据请求格式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

      // 二进制,默认
      manager.requestSerializer = [AFHTTPRequestSerializer serializer];

      // JSON
      manager.requestSerializer = [AFJSONRequestSerializer serializer];

      // Plist
      manager.requestSerializer = [AFPropertyListRequestSerializer serializer];
    • 设置数据响应格式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

      // 二进制
      manager.responseSerializer = [AFHTTPResponseSerializer serializer];

      // JSON,默认
      manager.responseSerializer = [AFJSONResponseSerializer serializer];

      // XMLParser,SAX 解析
      manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

      // Plist
      manager.responseSerializer = [AFPropertyListResponseSerializer serializer];

      // Image
      manager.responseSerializer = [AFImageResponseSerializer serializer];

      // Compound
      manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    • GET 请求

      • 数据请求

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        NSString *urlStr = @"http://192.168.88.200/demo.json";

        AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager];

        [manger GET:urlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);

        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"failure: %@", error);
        }];
      • 文件下载

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        NSString *urlStr = @"http://192.168.88.200/download/file/minion_01.mp4";

        AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager];

        // 设置接收数据的类型为二进制格式
        manger.responseSerializer = [AFHTTPResponseSerializer serializer];

        [manger GET:urlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

        [responseObject writeToFile:[operation.response.suggestedFilename q_appendDocumentPath] atomically:YES];

        NSLog(@"success: %@", [responseObject class]);

        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"failure: %@", error);
        }];
    • HEAD 请求

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      NSString *urlStr = @"http://192.168.88.200/download/file/minion_01.mp4";

      AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager];

      [manger HEAD:urlStr parameters:nil success:^(AFHTTPRequestOperation *operation) {

      NSLog(@"success: %@ --- %lld", operation.response.suggestedFilename, operation.response.expectedContentLength);

      } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

      NSLog(@"failure: %@", error);
      }];
    • POST 请求

      • 数据请求

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video";
        NSDictionary *params = @{@"type":@"JSON"};

        AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager];

        [manger POST:urlStr parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);

        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"failure: %@", error);
        }];
      • 文件上传

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        NSString *urlStr = @"http://192.168.88.200/upload/upload.php";

        AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager];

        [manger POST:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {

        NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HQ_0005.jpg" ofType:nil]];
        [formData appendPartWithFileData:fileData name:@"userfile" fileName:@"test.jpg" mimeType:@"image/jpg"];
        [formData appendPartWithFormData:[@"qian" dataUsingEncoding:NSUTF8StringEncoding] name:@"username"];

        } success:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);

        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"failure: %@", error);
        }];

7、AFHTTPSessionManager 的使用

  • Objective-C

    • Manager 的创建

      1
      2
      3
      4
      5
      6
      7
      8
      NSURL *baseURL = [NSURL URLWithString:@"http://192.168.88.200"];
      NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

      AFHTTPSessionManager *manager1 = [AFHTTPSessionManager manager];

      AFHTTPSessionManager *manager2 = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL];

      AFHTTPSessionManager *manager3 = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL sessionConfiguration:config];
    • 设置数据请求格式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

      // 二进制,默认
      manager.requestSerializer = [AFHTTPRequestSerializer serializer];

      // JSON
      manager.requestSerializer = [AFJSONRequestSerializer serializer];

      // Plist
      manager.requestSerializer = [AFPropertyListRequestSerializer serializer];
    • 设置数据响应格式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

      // 二进制
      manager.responseSerializer = [AFHTTPResponseSerializer serializer];

      // JSON,默认
      manager.responseSerializer = [AFJSONResponseSerializer serializer];

      // XMLParser,SAX 解析
      manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

      // Plist
      manager.responseSerializer = [AFPropertyListResponseSerializer serializer];

      // Image
      manager.responseSerializer = [AFImageResponseSerializer serializer];

      // Compound
      manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    • Request 设置

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

      // 设置参数编码方式,`NSUTF8StringEncoding` by default
      manager.requestSerializer.stringEncoding = NSUTF8StringEncoding;

      // 设置缓存策略,`NSURLRequestUseProtocolCachePolicy` by default.
      manager.requestSerializer.cachePolicy = NSURLRequestUseProtocolCachePolicy;

      // 设置网络服务类型,`NSURLNetworkServiceTypeDefault` by default.
      manager.requestSerializer.networkServiceType = NSURLNetworkServiceTypeDefault;

      // 设置请求超时时间,The default timeout interval is 60 seconds.
      manager.requestSerializer.timeoutInterval = 15;

      // 是否允许蜂窝网络访问,`YES` by default.
      manager.requestSerializer.allowsCellularAccess = YES;

      // 设置是否应用默认的 Cookies,`YES` by default.
      manager.requestSerializer.HTTPShouldHandleCookies = YES;

      // 设置是否使用 Pipelining,`NO` by default.
      manager.requestSerializer.HTTPShouldUsePipelining = NO;

      // 请求头设置

      // 设置请求头
      [manager.requestSerializer setValue:@"iPhone" forHTTPHeaderField:@"User-Agent"];

      // 设置用户验证
      [manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"admin" password:@"adminpasswd"];

      // 清除用户验证信息
      [manager.requestSerializer clearAuthorizationHeader];
    • GET 请求

      • 数据请求

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        NSString *urlStr = @"http://192.168.88.200/demo.json";

        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

        [manager GET:urlStr parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task,
        id _Nullable responseObject) {

        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);

        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        NSLog(@"failure: %@", error);
        }];
      • 文件下载

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        NSString *urlStr = @"http://192.168.88.200/download/file/minion_01.mp4";

        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

        // 设置接收数据的类型为二进制格式
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];

        [manager GET:urlStr parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {

        float progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount;

        dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil
        backgroundColor:[UIColor yellowColor]];
        });

        } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

        [responseObject writeToFile:[task.response.suggestedFilename q_appendDocumentPath] atomically:YES];

        NSLog(@"success: %@", [responseObject class]);

        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        NSLog(@"failure: %@", error);
        }];
    • HEAD 请求

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      NSString *urlStr = @"http://192.168.88.200/download/file/minion_01.mp4";

      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

      [manager HEAD:urlStr parameters:nil success:^(NSURLSessionDataTask * _Nonnull task) {

      NSLog(@"success: %@ --- %lld", task.response.suggestedFilename, task.response.expectedContentLength);

      } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

      NSLog(@"failure: %@", error);
      }];
    • POST 请求

      • 数据请求

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video";
        NSDictionary *params = @{@"type":@"JSON"};

        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

        [manager POST:urlStr parameters:params
        progress:nil
        success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);

        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        NSLog(@"failure: %@", error);
        }];
      • 文件上传

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        NSString *urlStr = @"http://192.168.88.200/upload/upload.php";

        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

        [manager POST:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {

        NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HQ_0005.jpg" ofType:nil]];
        [formData appendPartWithFileData:fileData name:@"userfile" fileName:@"test.jpg" mimeType:@"image/jpg"];
        [formData appendPartWithFormData:[@"qian" dataUsingEncoding:NSUTF8StringEncoding] name:@"username"];

        } progress:^(NSProgress * _Nonnull uploadProgress) {

        float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount;
        dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil
        backgroundColor:[UIColor yellowColor]];
        });

        } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);

        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        NSLog(@"failure: %@", error);
        }];

8、AFURLSessionManager 的使用

  • Objective-C

    • Manager 的创建

      1
      2
      3
      4
      5
      6
      // 创建 manager
      AFURLSessionManager *manager = [[AFURLSessionManager alloc]
      initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

      // 取消挂起的 task
      [[AFURLSessionManager alloc] invalidateSessionCancelingTasks:YES];
    • 设置数据响应格式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      AFURLSessionManager *manager = [[AFURLSessionManager alloc] 
      initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

      // 二进制
      manager.responseSerializer = [AFHTTPResponseSerializer serializer];

      // JSON,默认
      manager.responseSerializer = [AFJSONResponseSerializer serializer];

      // XMLParser,SAX 解析
      manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

      // Plist
      manager.responseSerializer = [AFPropertyListResponseSerializer serializer];

      // Image
      manager.responseSerializer = [AFImageResponseSerializer serializer];

      // Compound
      manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    • 获取上传下载进度

      1
      2
      3
      4
      5
      6
      7
      8
      AFURLSessionManager *manager = [[AFURLSessionManager alloc] 
      initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

      // 获取上传进度
      NSProgress *uploadProgress = [manager uploadProgressForTask:uploadTask];

      // 获取下载进度
      NSProgress *downloadProgress = [manager uploadProgressForTask:downloadTask];
    • Data Tasks

      • GET 数据请求

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:
        @"http://192.168.88.200:8080/MJServer/video?type=JSON"]];

        AFURLSessionManager *manager = [[AFURLSessionManager alloc]
        initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

        [[manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response,
        id _Nullable responseObject,
        NSError * _Nullable error) {

        if (error == nil && responseObject != nil) {
        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);
        } else {
        NSLog(@"failure: %@", error);
        }
        }] resume];
      • POST 数据请求

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:
        @"http://192.168.88.200:8080/MJServer/video"]];
        request.HTTPMethod = @"POST";
        request.HTTPBody = [@"type=JSON" dataUsingEncoding:NSUTF8StringEncoding];

        AFURLSessionManager *manager = [[AFURLSessionManager alloc]
        initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

        [[manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response,
        id _Nullable responseObject,
        NSError * _Nullable error) {

        if (error == nil && responseObject != nil) {
        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);
        } else {
        NSLog(@"failure: %@", error);
        }
        }] resume];
    • Upload Tasks

      • POST 文件上传

        • 文件数据封装使用到第三方框架 QExtension,具体实现代码见 GitHub 源码 QExtension

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:
          @"http://192.168.88.200/upload/upload.php"]];
          request.HTTPMethod = @"POST";

          NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HQ_0005.jpg" ofType:nil]];
          NSData *formData = [NSData q_formDataWithRequest:request
          text:@"qian"
          textName:@"username"
          fileData:fileData
          name:@"userfile"
          fileName:@"test.jpg"
          mimeType:@"imge/jpg"];

          AFURLSessionManager *manager = [[AFURLSessionManager alloc]
          initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

          [[manager uploadTaskWithRequest:request fromData:formData progress:^(NSProgress * _Nonnull uploadProgress) {

          float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount;
          dispatch_async(dispatch_get_main_queue(), ^{
          [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]];
          });

          } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {

          if (error == nil && responseObject != nil) {
          NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);
          } else {
          NSLog(@"failure: %@", error);
          }
          }] resume];
      • POST 文件上传,fileData 形式

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        NSString *urlStr = @"http://192.168.88.200/upload/upload.php";

        NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer]
        multipartFormRequestWithMethod:@"POST"
        URLString:urlStr
        parameters:nil
        constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {

        // 指定文件数据形式上传

        NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HQ_0005.jpg" ofType:nil]];
        [formData appendPartWithFileData:fileData name:@"userfile" fileName:@"test.jpg" mimeType:@"imge/jpg"];
        [formData appendPartWithFormData:[@"qian" dataUsingEncoding:NSUTF8StringEncoding] name:@"username"];

        } error: NULL];

        AFURLSessionManager *manager = [[AFURLSessionManager alloc]
        initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

        [[manager uploadTaskWithStreamedRequest:request progress:^(NSProgress * _Nonnull uploadProgress) {

        float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount;
        dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]];
        });

        } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {

        if (error == nil && responseObject != nil) {
        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);
        } else {
        NSLog(@"failure: %@", error);
        }
        }] resume];
      • POST 文件上传,fileUrl 形式

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        NSString *urlStr = @"http://192.168.88.200/upload/upload.php";

        NSMutableURLRequest *urlRequest = [[AFHTTPRequestSerializer serializer]
        multipartFormRequestWithMethod:@"POST"
        URLString:urlStr
        parameters:nil
        constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {

        // 指定文件路径形式上传

        NSURL *fileUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"HQ_0005" ofType:@"jpg"]];
        [formData appendPartWithFileURL:fileUrl name:@"userfile" fileName:@"test.png" mimeType:@"image/jpg" error:nil];
        [formData appendPartWithFormData:[@"qian" dataUsingEncoding:NSUTF8StringEncoding] name:@"username"];

        } error: NULL];

        AFURLSessionManager *manager = [[AFURLSessionManager alloc]
        initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

        [[manager uploadTaskWithStreamedRequest:urlRequest progress:^(NSProgress * _Nonnull uploadProgress) {

        float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount;
        dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]];
        });

        } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {

        if (error == nil && responseObject != nil) {
        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);
        } else {
        NSLog(@"failure: %@", error);
        }
        }] resume];
      • PUT 文件上传

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:
        @"http://192.168.88.200/uploads/123.jpg"]];
        request.HTTPMethod = @"PUT";

        [request setValue:[@"admin:adminpasswd" q_basic64AuthEncode] forHTTPHeaderField:@"Authorization"];

        NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"HQ_0005.jpg" withExtension:nil];

        AFURLSessionManager *manager = [[AFURLSessionManager alloc]
        initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];

        [[manager uploadTaskWithRequest:request fromFile:fileURL progress:^(NSProgress * _Nonnull uploadProgress) {

        float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount;
        dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]];
        });

        } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {

        if (error == nil && responseObject != nil) {
        NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);
        } else {
        NSLog(@"failure: %@", error);
        }
        }] resume];
    • Download Tasks

      • 普通下载

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.88.200/download/file/minion_01.mp4"]];

        AFURLSessionManager *manager = [[AFURLSessionManager alloc]
        initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

        [[manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {

        float progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount;
        dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]];
        });

        } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {

        return [NSURL fileURLWithPath:[response.suggestedFilename q_appendDocumentPath]];

        } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {

        if (error == nil) {
        NSLog(@"success: %@ --- %@", response, [response class]);
        } else {
        NSLog(@"failure: %@", error);
        }
        }] resume];
      • 断点下载

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        70
        71
        72
        73
        74
        75
        76
        77
        78
        79
        80
        81
        82
        83
        84
        85
        86
        87
        88
        89
        90
        91
        92
        93
        94
        95
        96
        97
        98
        99
        100
        101
        102
        103
        104
        105
        106
        107
        108
        109
        110
        111
        112
        113
        114
        115
        116
        117
        118
        119
        120
        121
        122
        123
        124
        125
        126
        127
        128
        129
        130
        131
        132
        133
        134
        135
        136
        137
        138
        139
        140
        141
        142
        143
        144
        145
        146
        147
        148
        149
        150
        151
        152
        153
        154
        155
        156
        157
        158
        159
        160
        161
        162
        163
        164
        165
        166
        167
        168
        169
        170
        171
        172
        173
        174
        175
        176
        177
        178
        179
        180
        181
        182
        183
        184
        185
        186
        187
        188
        189
        190
        191
        192
        193
        194
        @property (nonatomic, strong) AFURLSessionManager *manager;
        @property (nonatomic, retain) NSURLSessionDownloadTask *downloadTask;

        @property (nonatomic, strong) NSData *resumeData;
        @property (nonatomic, strong) NSString *resumeTmpPath;

        @property (nonatomic, assign) BOOL isDownloading;
        @property (nonatomic, assign) BOOL isPause;

        - (AFURLSessionManager *)manager {
        if (_manager == nil) {
        _manager = [[AFURLSessionManager alloc]
        initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
        _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        }
        return _manager;
        }

        - (NSString *)resumeTmpPath {
        if (_resumeTmpPath == nil) {
        _resumeTmpPath = [@"resumeTmpData.tmp" q_appendCachePath];
        }
        return _resumeTmpPath;
        }

        // 开始下载

        - (void)start {

        if (self.isDownloading) {
        NSLog(@"已经开始下载");
        return;
        }

        if (self.isPause) {

        NSLog(@"继续下载");

        [self.downloadTask resume];

        self.isPause = NO;
        self.isDownloading = YES;
        return;
        }

        if (![[NSFileManager defaultManager] fileExistsAtPath:self.resumeTmpPath]) {

        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:
        @"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]];

        self.downloadTask = [self.manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {

        [self downloadProgress:downloadProgress];

        } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {

        return [NSURL fileURLWithPath:[response.suggestedFilename q_appendDocumentPath]];

        } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {

        [self downloadCompletion:filePath error:error];
        }];

        [self.downloadTask resume];

        self.isPause = NO;
        self.isDownloading = YES;

        } else {
        [self goon];
        }
        }

        // 继续下载

        - (void)goon {

        if (self.isDownloading) {
        NSLog(@"已经开始下载");
        return;
        }

        if (self.isPause) {

        [self.downloadTask resume];
        NSLog(@"继续下载");

        } else {

        self.resumeData = [NSData dataWithContentsOfFile:self.resumeTmpPath];

        self.downloadTask = [self.manager downloadTaskWithResumeData:self.resumeData
        progress:^(NSProgress * _Nonnull downloadProgress) {

        [self downloadProgress:downloadProgress];

        } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {

        return [NSURL fileURLWithPath:[response.suggestedFilename q_appendDocumentPath]];

        } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {

        [self downloadCompletion:filePath error:error];
        }];

        [self.downloadTask resume];

        NSLog(@"继续下载");
        }

        self.isPause = NO;
        self.isDownloading = YES;
        }

        // 暂停下载

        - (void)pause {

        if (!self.isDownloading) {
        NSLog(@"已经停止下载");
        return;
        }

        [self.downloadTask suspend];

        NSLog(@"暂停下载");

        self.isPause = YES;
        self.isDownloading = NO;
        }

        // 停止下载

        - (void)stop {

        if (!self.isDownloading) {
        NSLog(@"已经停止下载");
        return;
        }

        [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {

        if (resumeData) {

        self.resumeData = resumeData;

        [self.resumeData writeToFile:self.resumeTmpPath atomically:YES];
        }

        self.downloadTask = nil;

        NSLog(@"停止下载");
        }];

        self.isDownloading = NO;
        }

        - (void)downloadProgress:(NSProgress *)downloadProgress {

        float progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount;
        dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil
        backgroundColor:[UIColor yellowColor]];
        });
        }

        - (void)downloadCompletion:(NSURL *)filePath error:(NSError *)error {

        self.isDownloading = NO;

        if (error == nil) {

        NSLog(@"success: %@", filePath.path);

        [[NSFileManager defaultManager] removeItemAtPath:self.resumeTmpPath error:nil];

        } else {

        NSLog(@"%@", error);

        if (error) {
        NSLog(@"failure: %@", error.userInfo[NSLocalizedDescriptionKey]);

        self.resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
        }

        if ([error.localizedFailureReason isEqualToString:@"No such file or directory"]) {

        [[NSFileManager defaultManager] removeItemAtPath:self.resumeTmpPath error:nil];

        [self start];
        }
        }
        }

9、AFNetworking 单例封装

  • Objective-C

    • NetworkTools.h

      1
      2
      3
      4
      5
      6
      7
      #import <AFNetworking/AFNetworking.h>

      @interface NetworkTools : AFHTTPSessionManager

      + (instancetype)sharedNetworkTools;

      @end
    • NetworkTools.m

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      @implementation NetworkTools

      + (instancetype)sharedNetworkTools {
      static NetworkTools *tools;

      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{

      // baseURL 的目的,就是让后续的网络访问直接使用 相对路径即可,baseURL 的路径一定要有 / 结尾
      NSURL *baseURL = [NSURL URLWithString:@"http://c.m.163.com/"];

      NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

      tools = [[self alloc] initWithBaseURL:baseURL sessionConfiguration:config];

      // 修改 解析数据格式 能够接受的内容类型 - 官方推荐的做法,民间做法:直接修改 AFN 的源代码
      tools.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",
      @"text/json",
      @"text/javascript",
      @"text/html",
      nil];
      });
      return tools;
      }

      @end
文章目录
  1. 1. 前言
  2. 2. 1、AFNetworking
    1. 2.1. 1.1 AFNetworking 特点
    2. 2.2. 1.2 AFNetworking 官方使用建议
    3. 2.3. 1.3 AFNetworking 系统需求
    4. 2.4. 1.4 AFNetworking 框架结构
  3. 3. 2、AFNetworking 的添加
  4. 4. 3、AFNetworking 的设置
  5. 5. 4、AFNetworking 网络状态监测
  6. 6. 5、AFNetworking 安全策略设置
  7. 7. 6、AFHTTPRequestOperationManager 的使用
  8. 8. 7、AFHTTPSessionManager 的使用
  9. 9. 8、AFURLSessionManager 的使用
  10. 10. 9、AFNetworking 单例封装
隐藏目录