iOS网络---AFNetworking

系列文章目录

iOS基础—Block
iOS基础—Protocol
iOS基础—KVC vs KVO
iOS网络—AFNetworking
iOS网络—NSURLSession
iOS内存管理—MRC vs ARC
iOS基础—Category vs Extension
iOS基础—多线程:GCD、NSThread、NSOperation
iOS基础—常用三方库:Masonry、SDWebImage
iOS基础—定时器:GCD、NSTimer、CADisplayLink



一、和NSURLSession的关系

AFNetworking 是一个基于 NSURLSession 和 NSURLConnection 的强大网络库,旨在简化 iOS 和 macOS 应用中的网络请求和响应处理。NSURLSession 是 Apple 提供的基础网络库,而 AFNetworking 则在其基础上进行了封装,提供了更高层次的抽象和更多的功能。

NSURLSession简介:

NSURLSession 是 Apple 提供的基础网络库,用于处理 HTTP/HTTPS 请求。它提供了以下功能:

  1. 数据任务 (NSURLSessionDataTask)
  2. 下载任务 (NSURLSessionDownloadTask)
  3. 上传任务 (NSURLSessionUploadTask)
  4. 支持后台下载和上传
  5. 支持自定义会话配置 (NSURLSessionConfiguration)
  6. 支持代理 (NSURLSessionDelegate)

AFNetworking (github🔗)简介:

AFNetworking 是一个基于 NSURLSession 的第三方网络库(3.0版本中的 NSURLConnection 已被全部弃用),提供了更高层次的抽象和更多的功能。主要特点包括:

  1. 简化网络请求的创建和管理
  2. 支持 JSON、XML、Plist 等多种数据格式解析
  3. 内置图片下载和缓存功能
  4. 提供网络状态监控
  5. 支持安全的 HTTPS 请求
  6. 支持后台下载和上传
  7. 提供了更灵活的请求和响应处理机制

AFNetworking 与 NSURLSession 的关系:

  1. 封装与扩展
    AFNetworking 通过对 NSURLSession 的封装,简化了网络请求的创建和管理。它提供了更简洁的 API,使开发者可以更方便地进行网络操作。
  2. 高层次抽象
    AFNetworking 提供了更高层次的抽象,隐藏了许多底层实现细节。开发者可以通过简单的 API 发起网络请求,而无需关心底层的实现和配置。
  3. 额外功能
    AFNetworking 在 NSURLSession 的基础上,增加了许多额外的功能,如:
  • 请求和响应处理:提供了更灵活的请求和响应处理机制,可以方便地进行数据解析和错误处理。
  • 图片下载和缓存:内置了图片下载和缓存功能,适用于需要加载图片的应用。
  • 网络状态监控:提供了网络状态监控功能,可以检测网络连接的变化。

二、AFNetworking的架构

AFNetworking 框架主要包含两部分:

  • AFNetworking 核心功能
  • UIKit+AFNetworking 分类功能

目录结构如下:

  1. 网络通信模块(AFURLSessionManager、AFHTTPSessionManger)
  2. 网络状态监听模块(Reachability)
  3. 网络通信安全策略模块(Security)
  4. 网络通信数据序列化/反序列化模块(Serialization)
  5. 对于iOS UIKit库的扩展(UIKit)

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/08cc42c2b2f844338cd3913219eb14f9.png

三、AFURLSessionManager解析

1.持有属性

首先来看看 AFURLSessionManager 持有的公有属性:

@interface AFURLSessionManager : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, NSSecureCoding, NSCopying>

/// 管理的 Session
@property (readonly, nonatomic, strong) NSURLSession *session; 

 /// 代理回调执行的队列
@property (readonly, nonatomic, strong) NSOperationQueue *operationQueue;

/// 通过使用dataTaskWithRequest:success:failure:创建的数据任务,并使用GET/POST/等方便方法运行,服务器发送的响应会自动由响应序列化器进行验证和序列化。
/// 默认情况下,此属性被设置为AFJSONResponseSerializer的一个实例。
@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer; 

/// 由创建的会话用于评估安全连接的服务器信任的安全策略。AFURLSessionManager使用defaultPolicy,除非另有指定。
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;

///网络可达性管理器。AFURLSessionManager默认使用sharedManager。
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;

/// 当前由托管 session 运行的数据、上传和下载任务。
@property (readonly, nonatomic, strong) NSArray <NSURLSessionTask *> *tasks;

@property (readonly, nonatomic, strong) NSArray <NSURLSessionDataTask *> *dataTasks;
@property (readonly, nonatomic, strong) NSArray <NSURLSessionUploadTask *> *uploadTasks;
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDownloadTask *> *downloadTasks;

/// The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used.
@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue;

/// The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used.
@property (nonatomic, strong, nullable) dispatch_group_t completionGroup;

私有属性如下,可以做了解:

@interface AFURLSessionManager ()
@property (readwrite, nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration;
@property (readwrite, nonatomic, strong) NSOperationQueue *operationQueue;
@property (readwrite, nonatomic, strong) NSURLSession *session;
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier;
@property (readonly, nonatomic, copy) NSString *taskDescriptionForSessionTasks;
@property (readwrite, nonatomic, strong) NSLock *lock;
@property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
@property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession AF_API_UNAVAILABLE(macos);
@property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection;
@property (readwrite, nonatomic, copy) AFURLSessionTaskAuthenticationChallengeBlock authenticationChallengeHandler;
@property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidSendBodyDataBlock taskDidSendBodyData;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidCompleteBlock taskDidComplete;
#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidFinishCollectingMetricsBlock taskDidFinishCollectingMetrics AF_API_AVAILABLE(ios(10), macosx(10.12), watchos(3), tvos(10));
#endif
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveResponseBlock dataTaskDidReceiveResponse;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskWillCacheResponseBlock dataTaskWillCacheResponse;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidWriteDataBlock downloadTaskDidWriteData;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidResumeBlock downloadTaskDidResume;
@end

2.初始化

源码中 AFURLSessionManager 的初始化方法如下:

- (instancetype)init {
    return [self initWithSessionConfiguration:nil];
}

- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    self = [super init];
    if (!self) {
        return nil;
    }

    if (!configuration) {
        configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    }

    self.sessionConfiguration = configuration;

    self.operationQueue = [[NSOperationQueue alloc] init];
    self.operationQueue.maxConcurrentOperationCount = 1;

    self.responseSerializer = [AFJSONResponseSerializer serializer];

    self.securityPolicy = [AFSecurityPolicy defaultPolicy];

#if !TARGET_OS_WATCH
    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif

    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

    self.lock = [[NSLock alloc] init];
    self.lock.name = AFURLSessionManagerLockName;

    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        for (NSURLSessionDataTask *task in dataTasks) {
            [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
        }

        for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
            [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
        }

        for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
            [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
        }
    }];

    return self;
}

我们可以总结一下初始化流程:

  1. 初始化 sessionConfiguration、operationQueue、responseSerializer等属性,大部分都是 default 配置。
  2. 调用 getTasksWithCompletionHandler: 方法获取当前 session 中的 tasks,并为 tasks 设置代理,处理返回的数据

3.进度管理

AFURLSessionManager 作为会话对象的代理,基本可以处理所有任务对象。但是,对于上传任务、下载任务进行进度管理,使用 AFURLSessionManager 来管理是较为繁琐的,也是不合理的。主要有以下几点原因:

  • 在上传任务和下载任务的整个生命周期中都需要持有一个进度对象 NSProgress。
    NSProgress 是 Apple 提供的一个类,用于跟踪和报告任务的进度。它在处理长时间运行的任务(如文件下载、数据处理等)时非常有用。NSProgress 可以在多个线程之间共享进度信息,并且支持嵌套进度对象,从而提供更细粒度的进度跟踪。
  • 在下载任务的整个生命周期中还需要持有一个接收数据对象,用于持续接收数据。
  • AFURLSessionManager 主要用于管理会话,根据职责单一原则,它不应该管理任务对象的具体细节。

因此,AFNetworking 提供了 AFURLSessionManagerTaskDelegate 这样一个内部类,用于处理 NSURLSessionTask 的代理回调。它是 AFURLSessionManager 的辅助类,负责处理任务的进度、完成、失败等事件。通过使用这个代理类,AFNetworking 可以更好地管理和处理各种网络任务。

AFURLSessionManager 内部维护了一个可变字典属性 mutableTaskDelegatesKeyedByTaskIdentifier,以任务对象的标识符 taskIdentifier 作为键,以 AFURLSessionManagerTaskDelegate 对象作为值。在初始化任务对象时,就绑定一个 AFURLSessionManagerTaskDelegate 对象,以处理进度、下载数据。

在这里插入图片描述

具体的代码逻辑如下:

//  根据特定 request 创建一个 NSURLSessionDataTask
- (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 {
		
    // 创建任务对象
    NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];
		
    // 为任务对象设置代理对象、上传进度回调、下载进度回调、完成回调
    [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

    return dataTask;
}

// 中间调用了 addDelegateForDataTask:uploadProgress:downloadProgress:completionHandler: 方法
- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
                uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
              downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
             completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
	// 创建一个 AFURLSessionManagerTaskDelegate 对象,用以处理进度、下载数据
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];
    delegate.manager = self;
    delegate.completionHandler = completionHandler;
    
	// 用来标识任务对象所属的 SessionManager
    dataTask.taskDescription = self.taskDescriptionForSessionTasks;
    [self setDelegate:delegate forTask:dataTask];

    delegate.uploadProgressBlock = uploadProgressBlock;
    delegate.downloadProgressBlock = downloadProgressBlock;
}

// 其中又调用了 setDelegate:forTask: 方法
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
            forTask:(NSURLSessionTask *)task
{
    NSParameterAssert(task);
    NSParameterAssert(delegate);

    [self.lock lock];
    // 保存 NSURLSessionTask <-> AFURLSessionManagerTaskDelegate 的映射关系
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    [self addNotificationObserverForTask:task];
    [self.lock unlock];
}

AFURLSessionManagerTaskDelegate 主要实现了以下这些协议方法。在这些方法内实现进度管理、下载管理。AFURLSessionManager 虽然也实现了这些协议,但是最终还是会调用 AFURLSessionManagerTaskDelegate 中的实现。

  • NSURLSessionTaskDelegate
    URLSession:task:didCompleteWithError:
    URLSession:task:didFinishCollectingMetrics:
  • NSURLSessionDataDelegate
    URLSession:dataTask:didReceiveData:
    URLSession:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
  • NSURLSessionDownloadDelegate
    URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
    URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
    URLSession:downloadTask:didFinishDownloadingToURL:

4.通知转发

NSURLSession 定义了一系列通知,为了提供更完美的封装,AFURLSessionManager 捕获了这些通知,将它们转换成自己所定义的通知后,再进行转发。

这里,就用到了任务对象的 taskDescription 属性。taskDescription 属性描述了该任务对象所属的 Session Manager。因为应用程序中可能会初始化多个 AFURLSessionManager。Session Manager 只有在捕获到它所管理的任务对象发出的通知后才会进行封装和转发。如:

  • AFNetworkingTaskDidResumeNotification
  • AFNetworkingTaskDidSuspendNotification
//当任务恢复时,AFURLSessionManager 会捕获 NSURLSessionTaskDidResumeNotification 通知,并检查任务的描述是否与 taskDescriptionForSessionTasks 匹配。
//如果匹配,则发送自定义的 AFNetworkingTaskDidResumeNotification 通知。
- (void)taskDidResume:(NSNotification *)notification {
    NSURLSessionTask *task = notification.object;
    if ([task respondsToSelector:@selector(taskDescription)]) {
        if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidResumeNotification object:task];
            });
        }
    }
}

//当任务暂停时,AFURLSessionManager 会捕获 NSURLSessionTaskDidSuspendNotification 通知,并检查任务的描述是否与 taskDescriptionForSessionTasks 匹配。
//如果匹配,则发送自定义的 AFNetworkingTaskDidSuspendNotification 通知。
- (void)taskDidSuspend:(NSNotification *)notification {
    NSURLSessionTask *task = notification.object;
    if ([task respondsToSelector:@selector(taskDescription)]) {
        if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidSuspendNotification object:task];
            });
        }
    }
}

四、AFHTTPSessionManager解析

我们可以先来看看 AFHTTPSessionManager 持有的公有属性。由于,AFHTTPSessionManager 主要用于 HTTP 请求,所以它为 HTTP 请求提供了一个请求序列化器和一个响应序列化器,并分别设置默认值为 HTTP 和 JSON:

//在方法例如 requestWithMethod:URLString:parameters: 和 GET / POST / 等方便方法中,用于从相对路径构造请求的 URL。
@property (readonly, nonatomic, strong, nullable) NSURL *baseURL;

//使用requestWithMethod:URLString:parameters:和 multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:创建的请求
//通过使用此属性指定的参数序列化器构造默认的一组请求头。默认情况下,此属性设置为AFHTTPRequestSerializer的一个实例,它将查询字符串参数序列化为GET、HEAD和DELETE请求,或者将HTTP消息体进行URL编码。
@property (nonatomic, strong) AFHTTPRequestSerializer <AFURLRequestSerialization> * requestSerializer;

//使用dataTaskWithRequest:success:failure:创建并使用GET / POST / 等方便方法运行的数据任务,从服务器发送的响应会自动由响应序列化器进行验证和序列化。
//默认情况下,此属性设置为AFJSONResponseSerializer的一个实例。
@property (nonatomic, strong) AFHTTPResponseSerializer <AFURLResponseSerialization> * responseSerializer;


//由创建的会话用于评估安全连接的服务器信任的安全策略。 除非另有指定,否则AFURLSessionManager将使用defaultPolicy。 
//配置了AFSSLPinningModePublicKey或AFSSLPinningModeCertificate的安全策略只能应用于使用安全基础URL(即https)初始化的会话管理器。
//在不安全的会话管理器上应用启用了插销的安全策略会引发“Invalid Security Policy”异常。
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;

除此之外,AFHTTPSessionManager 还封装了 AFURLSessionManager 的一些复杂的任务对象初始化方法,并提供了一些非常简单的便利方法,用以提供各种 HTTP 请求。如下所示:

// 发送一个GET请求。
- (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
                            parameters:(nullable id)parameters
                               headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                              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
                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                                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
                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

// 发送一个带有构造体的POST请求。
- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                             parameters:(nullable id)parameters
                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
              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
                               headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                               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
                                 headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                                 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
                                  headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                                  success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                  failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

// 发送一个通用的HTTP请求。
- (nullable NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                                URLString:(NSString *)URLString
                                               parameters:(nullable id)parameters
                                                  headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                                           uploadProgress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                         downloadProgress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
                                                  success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                                  failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

五、使用示例

我们用 AFNetworking 来请求一张图片的数据,并展示到视图上:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // 初始化并配置 imgView
    self.imgView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
    self.imgView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:self.imgView];
    [self downloadImgAndSave];
}

// 下载图片并且保存
- (void)downloadImgAndSave {
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer]; //设置响应序列化器:
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"image/jpeg", nil];
    
    __weak __typeof__(self) weakSelf = self;
    NSString *url = @"http://www.pptbz.com/pptpic/UploadFiles_6909/201203/2012031220134655.jpg";
    
    // 开始下载
    [manager GET:url parameters:nil headers:nil progress:^(NSProgress *downloadProgress) {
        NSLog(@"progress:%lld",downloadProgress.completedUnitCount);
    } success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"图片下载完成");
        __strong __typeof__(weakSelf) strongSelf = weakSelf;
        strongSelf.imgView.image = [UIImage imageWithData:(NSData *)responseObject];
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        if (error) {
            NSLog(@"%@",error.userInfo);
        }
    }];
}

@end

运行的结果如下:
在这里插入图片描述

总而言之,AFNetworking 实际上只是对 NSURLSession 高度地封装, 提供一些简单易用的 API 方便我们在 iOS 开发中发出网络请求并在其上更快地构建网络层组件并提供合理的接口。我们这个实例也证明了它使用的简便性。

iOS开发中上传图片可以采用以下步骤: 1.选择要上传的图片,可以使用系统提供的UIImagePickerController控制器,或者使用第三方库,例如TZImagePickerController。 2.将选中的图片转换为NSData格式。 3.使用NSURLSession或AFNetworking网络库,将图片数据上传到服务器。 以下是一个简单的上传图片的示例代码: ``` // 选择图片 UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; imagePicker.delegate = self; [self presentViewController:imagePicker animated:YES completion:nil]; // 将选中的图片转换为NSData格式 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info { UIImage *selectedImage = info[UIImagePickerControllerOriginalImage]; NSData *imageData = UIImageJPEGRepresentation(selectedImage, 0.5); // 上传图片到服务器 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration]; NSURL *url = [NSURL URLWithString:@"http://example.com/upload.php"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST"; NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 处理服务器返回的响应 }]; [uploadTask resume]; [picker dismissViewControllerAnimated:YES completion:nil]; } ``` 其中,upload.php是服务器端接收图片的脚本文件。在服务器端,可以使用PHP等语言来处理上传的图片数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值