0%

AFNetworking—— 优雅的网络框架

  • GitHub 源码:AFNetworking
  • star:30000+

README 文档


AFNetworking 是一个适用于 iOS 系统和 Mac OS X 系统的网络框架。它建立在 Foundation URL Loading System 之上,扩展了 Cocoa 强大的高级网络抽象。设计精良的模块化架构、功能丰富的 API,让你能够安心的使用,轻松实现各种网络请求,比如 GET 请求,POST 请求,以及上传多张图片等。

如何开始

  • Download AFNetworking and try out the included Mac and iPhone example apps
  • Read the “Getting Started” guide, FAQ, or other articles on the Wiki
  • Check out the documentation for a comprehensive look at all of the APIs available in AFNetworking
  • Read the AFNetworking 3.0 Migration Guide for an overview of the architectural changes from 2.0.

讨论

  • If you need help, use Stack Overflow. (Tag ‘afnetworking’)
  • If you’d like to ask a general question, use Stack Overflow.
  • If you found a bug, and can provide steps to reliably reproduce it, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

安装

AFNetworking 支持在项目中安装库的多种方法。

CocoaPods 安装

CocoaPods is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like AFNetworking in your projects. See the “Getting Started” guide for more information. You can install it with the following command:

$ gem install cocoapods

CocoaPods 0.39.0+ is required to build AFNetworking 3.0.0+.

配置

To integrate AFNetworking into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

target 'TargetName' do
pod 'AFNetworking', '~> 3.0'
end

Then, run the following command:

$ pod install

Carthage 安装

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate AFNetworking into your Xcode project using Carthage, specify it in your Cartfile:

github "AFNetworking/AFNetworking" ~> 3.0

Run carthage to build the framework and drag the built AFNetworking.framework into your Xcode project.

版本要求

AFNetworking Version Minimum iOS Target Minimum OS X Target Minimum watchOS Target Minimum tvOS Target Notes
3.x iOS 7 OS X 10.9 watchOS 2.0 tvOS 9.0 Xcode 7+ is required. NSURLConnectionOperation support has been removed.
2.6 -> 2.6.3 iOS 7 OS X 10.9 watchOS 2.0 n/a Xcode 7+ is required.
2.0 -> 2.5.4 iOS 6 OS X 10.8 n/a n/a Xcode 5+ is required. NSURLSession subspec requires iOS 7 or OS X 10.9.
1.x iOS 5 Mac OS X 10.7 n/a n/a
0.10.x iOS 4 Mac OS X 10.6 n/a n/a

(OS X projects must support 64-bit with modern Cocoa runtime).

Programming in Swift? Try Alamofire for a more conventional set of APIs.

结构

NSURLSession

  • AFURLSessionManager
  • AFHTTPSessionManager

序列化

  • <AFURLRequestSerialization> 请求序列化
    • AFHTTPRequestSerializer
    • AFJSONRequestSerializer
    • AFPropertyListRequestSerializer
  • <AFURLResponseSerialization> 响应序列化
    • AFHTTPResponseSerializer
    • AFJSONResponseSerializer
    • AFXMLParserResponseSerializer
    • AFXMLDocumentResponseSerializer (Mac OS X)
    • AFPropertyListResponseSerializer
    • AFImageResponseSerializer
    • AFCompoundResponseSerializer

其他功能

  • AFSecurityPolicy
  • AFNetworkReachabilityManager

结构图

006tKfTcly1fj0ndu06qaj307f0bqmye.jpg

用法

一、AFURLSessionManager

  • AFURLSessionManager 创建并管理 NSURLSession 对象。
  • NSURLSession 对象基于指定的 NSURLSessionConfiguration 对象。
  • NSURLSessionConfiguration 对象遵守如下协议: <NSURLSessionTaskDelegate>, <NSURLSessionDataDelegate>, <NSURLSessionDownloadDelegate>, 和 <NSURLSessionDelegate>

NSURLSessionTask

NSURLSessionDelegate 委托协议

1. 创建下载任务

// 1.创建 NSURLSessionConfiguration 对象
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

// 2.创建 AFURLSessionManager 对象
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

// 3.创建 NSURL、NSURLRequest 对象
NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

// 4.创建 NSURLSessionDownloadTask 对象
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
    NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
    return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
    NSLog(@"File downloaded to: %@", filePath);
}];
// 5.开启下载任务
[downloadTask resume];

2. 创建上传任务

// 1.创建 NSURLSessionConfiguration 对象
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

// 2.创建 AFURLSessionManager 对象
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

// 3.创建 NSURL、NSURLRequest 对象
NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

// 4.创建 NSURLSessionUploadTask 对象
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        NSLog(@"Error: %@", error);
    } else {
        NSLog(@"Success: %@ %@", response, responseObject);
    }
}];
// 5.开启下载任务
[uploadTask resume];

3. 创建一个单次含有多个信息的有进度指示的上传任务

// 1.创建 NSMutableURLRequest 对象
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
} error:nil];

// 2.创建 AFURLSessionManager 对象
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

// 3.创建 NSURLSessionUploadTask 对象
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
              uploadTaskWithStreamedRequest:request
              progress:^(NSProgress * _Nonnull uploadProgress) {
                  // 此处不会在主线程上回调
                  // 你要负责在主线程上更新 UI
                  dispatch_async(dispatch_get_main_queue(), ^{
                      // Update the progress view
                      [progressView setProgress:uploadProgress.fractionCompleted];
                  });
              }
              completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
                  if (error) {
                      NSLog(@"Error: %@", error);
                  } else {
                      NSLog(@"%@ %@", response, responseObject);
                  }
              }];
// 4.开启下载任务
[uploadTask resume];

4. 创建数据任务

// 1.创建 NSURLSessionConfiguration 对象
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

// 2.创建 AFURLSessionManager 对象
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

// 3.创建 NSURL、NSURLRequest 对象
NSURL *URL = [NSURL URLWithString:@"http://httpbin.org/get"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

// 4.创建 NSURLSessionDataTask 对象
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        NSLog(@"Error: %@", error);
    } else {
        NSLog(@"%@ %@", response, responseObject);
    }
}];

// 5.开启下载任务
[dataTask resume];

从使用上看,AFURLSessionManager 只是封装了原生的 NSURLSession 对象,创建网络请求步骤流程与原生方法(使用 NSURLSession 类)类似:

AFURLSessionManager


二、AFHTTPSessionManager

💡说明:官方 README 文档中并没有给出该类的示例代码,这里补充。

AFHTTPSessionManagerAFURLSessionManager 的子类对象,它提供了进行 HTTP 请求的便捷方法。当设置好 baseURL (服务器地址)时,要发起 GETPOST 等请求,你可以使用一些便捷方法,而这些便捷方法只需要传入相对路径参数即可。

总之,AFHTTPSessionManager 提供了发起 GETHEADPOSTPUTPATCHDELETE 请求的便捷语法。它调用的是父类 AFURLSessionManagerNSURLSessionDataTask 类型的任务。

这个类并没有实现像 NSURLSessionUploadTaskNSURLSessionDownloadTaskNSURLSessionStreamTask 类型的任务。

初始化方法:

+ (instancetype)manager;
- (instancetype)initWithBaseURL:(nullable NSURL *)url;
- (instancetype)initWithBaseURL:(nullable NSURL *)url
           sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration;

发起 HTTP 请求:

// GET
- (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
- (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;

- (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;

一、GET 请求

// 1.创建 AFHTTPSessionManager 对象
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

// 2.构建参数,parameters 参数可以传 nil
NSString *urlString = @"https://www.google.com/login";

// 3.Task 任务
[manager GET:urlString parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
    // 进度
} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    // 请求成功
    // task:通过task拿到响应头
    // responseObject:请求成功返回的响应结果(AFN内部已经把响应体转换为OC对象,通常是字典或数组)
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    // 请求失败
    NSLog(@"GET ERROR:%@",error.localizedDescription);
}];

二、POST 请求

// 1.创建 AFHTTPSessionManager 对象
AFHTTPSessionManager *manager = [AFHTTPSessionManager alloc]
    initWithBaseURL:[NSURL URLWithString:@"https://www.google.com"]];

// 2.构建参数
NSString *relativePaths = @"/login";
NSDictionary *parameters = @{
                             @"username":@"admin",
                             @"password":@"123456",
                             };
// 3.Task 任务
[manager POST:relativePaths parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
    // 进度
} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    // 请求成功
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    // 请求失败
}]

其他设置

timeoutInterval 设置请求超时时间,默认为 60s:
// 设置请求超时时间为 10s
[manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
manager.requestSerializer.timeoutInterval = 10.f;
[manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
ContentTypes 类型
// AFN默认接收的 ContentTypes 有以下三种:
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];

// 如果服务器返回的 ContentTypes 类型为 text/html,需要设置如下:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
responseSerializer 默认把服务器返回的数据当做是 JSON 类型并自动转化为 Objec
// 设置为 XML 类型,此时返回的是 NSXMLParser 类型,需要我们自己解析。
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

// 设置为其他类型
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
验证 SSL 证书
// 验证CN域名
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc]initWithObjects:cerData, nil]];

// 是否信任具有无效或过期SSL证书的服务器(自建证书)
manager.securityPolicy.allowInvalidCertificates = YES;

// 是否在证书的CN字段中验证域名
manager.securityPolicy.validatesDomainName = NO;

设置状态栏活动指示器

启用后,系统会自动在应用程序发起网络请求时,在状态栏显示旋转的菊花。

  1. 在项目的 AppDelegate.m 文件中导入 AFNetworkActivityIndicatorManager.h 文件;
  2. AppDelegate application:didFinishLaunchingWithOptions: 方法中设置如下代码:
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];

请求序列化

请求序列化通过将请求参数编码为查询字符串或者 HTTP 请求体,来为 URL 字符串创建请求。

NSString *URLString = @"http://example.com";
NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]};

一、编码为查询字符串

// GET
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:URLString parameters:parameters error:nil];
GET http://example.com?foo=bar&baz[]=1&baz[]=2&baz[]=3

二、编码为 URL 表单

// POST
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters error:nil];
POST http://example.com/
Content-Type: application/x-www-form-urlencoded

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

三、编码为 JSON 字符串

// AFJSONRequestSerializer
[[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters error:nil];
POST http://example.com/
Content-Type: application/json

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

网络状态管理

AFNetworkReachabilityManager 类用于监测 WWAN 和 WiFi 接口的网络联通性。

  • 不要依据它来决定是否发起网络请求。
    • 你应该尝试发送网络请求。
  • 你可以依据它来选择是否自动重新发送请求。
    • 虽然它可能仍然失败,但当连接可用时,可访问性通知是重试某些东西的好时机。
  • 它是一个判断网络请求失败原因的很好用的工具。
    • 当网络请求失败时,告诉用户他们已经离线,要比告诉他们一些比如” 请求超时” 一类的准确的错误更好。

See also WWDC 2012 session 706, “Networking Best Practices.”.

共享网络状态连通性

示例:

AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
    switch (status) {
        case AFNetworkReachabilityStatusUnknown: {
            DDLogInfo(@"网络异常:未知网络");
            break;
        }
        case AFNetworkReachabilityStatusNotReachable: {
            DDLogInfo(@"网络异常:没有网络");
            break;
        }
        case AFNetworkReachabilityStatusReachableViaWWAN: {
            DDLogInfo(@"网络状态检测:蜂窝网络");
            break;
        }
        case AFNetworkReachabilityStatusReachableViaWiFi: {
            DDLogInfo(@"网络状态检测:WiFi");
            break;                
        }
    }
}];
[networkReachabilityManager startMonitoring]; // 开启网络检测

基于特定域名的网络连通性


安全策略

AFSecurityPolicy 基于 X.509 数字证书和公钥来确定服务器是否可信。

向应用程序中添加固定的 SSL 证书有助于防止中间人攻击和其他漏洞。强烈建议处理敏感客户数据或财务信息的应用程序通过 HTTPS 连接来和服务器通信。

允许无效的 SSL 证书

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy.allowInvalidCertificates = YES; // 生产环境不建议使用

单元测试

AFNetworking 在 Tests 子目录中包含一套单元测试。 这些测试可以简单地执行您想要测试的平台框架上的测试操作。

账户

AFNetworking is owned and maintained by the Alamofire Software Foundation.

AFNetworking was originally created by Scott Raymond and Mattt Thompson in the development of Gowalla for iPhone.

AFNetworking’s logo was designed by Alan Defibaugh.

And most of all, thanks to AFNetworking’s growing list of contributors.

Security Disclosure

If you believe you have identified a security vulnerability with AFNetworking, you should report it as soon as possible via email to security@alamofire.org. Please do not post it to a public issue tracker.

License

AFNetworking is released under the MIT license. See LICENSE for details.
tive-C 对象。

欢迎关注我的其它发布渠道