「OC」AFNetworking的简单使用

ops/2024/10/21 22:57:13/

「OC」AFNetworking的简单使用

前言

在我们进行网络申请的时候,直接使用OC之中自带的NSURLNSURLRequestNSURLSession进行相关操作,还需要实现Task回调、调用resume。那对我们进行开发来说还是相对比较繁琐的,为了简化我们的网络请求,我们其实可以直接使用AFNetworking这个第三方库进行网络请求的操作(下文简称AFN)。

介绍

我们先来对AFNetworking的核心组件进行介绍

AFHTTPSessionManager:基于 NSURLSession 的管理类,用于发送网络请求和处理响应。AFHTTPSessionManager 是最常用的类,用于处理 HTTP 请求。

AFURLSessionManager:基于 NSURLSession,用于管理下载、上传等任务。

AFNetworkReachabilityManager:用于监控网络状态的变化。

处理响应格式

AFNetworking 可以自动解析响应的数据格式,常用的解析格式有 JSON、XML、和图片。

  • JSON 响应: 默认情况下,AFHTTPSessionManager 会将服务器返回的 JSON 自动解析为字典或数组。

    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    
  • XML 响应: 如果你的服务器返回 XML,你可以使用 AFXMLParserResponseSerializer

    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
    
  • 图片下载: AFNetworking 也支持图片下载,并且可以设置下载的图片缓存。

    manager.responseSerializer = [AFImageResponseSerializer serializer];
    

进行简单的GET操作

我们以天气预报的信息申请为例子,如果使用OC之中原生的网络请求,代码大致如下

// 用 NSString 创建 URL
NSString *urlString = @"https://devapi.qweather.com/v7/weather/now?location=101110101&key=487fcdf6fdc9401da0ac4c4df535f43d";
NSURL *url = [NSURL URLWithString:urlString];// 创建 URLSession 对象
NSURLSession *session = [NSURLSession sharedSession];// 创建 URLRequest 对其进行相关请求,这里使用 GET 方法
NSURLRequest *request = [NSURLRequest requestWithURL:url];// 根据会话创建任务
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {//用block实现回调,处理接受的参数if (error) {NSLog(@"错误: %@", error);return;}NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;if (httpResponse.statusCode >= 200 && httpResponse.statusCode < 300) {NSError *jsonError;NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];if (jsonError) {NSLog(@"解析失败: %@", jsonError);} else {NSLog(@"数据如下: %@", json);// 在这里处理返回的数据}} else {NSLog(@"非法响应: %ld", (long)httpResponse.statusCode);}
}];// 启动任务
[task resume];

如果我们引入AFNetworking库,那么代码就会被简化为以下内容

// 导入 AFNetworking
#import <AFNetworking/AFNetworking.h>// 用 NSString 创建 URL
NSString *urlString = @"https://devapi.qweather.com/v7/weather/now?location=101110101&key=487fcdf6fdc9401da0ac4c4df535f43d";// 使用 AFHTTPSessionManager 来管理请求
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];// 设置响应格式为 JSON
manager.responseSerializer = [AFJSONResponseSerializer serializer];// 发起 GET 请求
[manager GET:urlString parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {// 请求成功,处理返回数据NSLog(@"数据如下: %@", responseObject);// 在这里处理返回的数据
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {// 请求失败,处理错误NSLog(@"错误: %@", error);
}];

我们可以看到,这个程序使用了AFNetworking之中的内容进行操作。其中,GET:parameters:headers:progress:success:failure: 方法是用于发送 GET 请求的基本 API。

responseObject 是返回的数据,AFNetworking 会自动解析 JSON。

添加请求头的GET操作

我们在进行网络请求的时候,有时候会需要用上请求头才能完成完整的网络请求,那我们需要在session的主体之中添加一个请求头。

如果使用OC原生的代码,那么操作还是很繁琐的,拿我们使用Spotify的艺术家申请,代码大致如下

- (void)getArtistInfo:(NSString *)artistID accessToken:(NSString *)accessToken {NSString *urlString = [NSString stringWithFormat:@"https://api.spotify.com/v1/artists/%@",artistID];NSURL *url = [NSURL URLWithString:urlString];NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];[request setHTTPMethod:@"GET"];[request setValue:[NSString stringWithFormat:@"Bearer %@", accessToken] forHTTPHeaderField:@"Authorization"];NSURLSession *session = [NSURLSession sharedSession];NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {if (error) {NSLog(@"%@", error.localizedDescription);return;}NSError *jsonError;NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];if (jsonError) {NSLog(@"%@", jsonError.localizedDescription);return;}Artist *art = [Artist yy_modelWithDictionary:json];NSLog(@"Artist Info:%@",json);NSLog(@"Artist Info: %ld", (long)art.followersTotal);}];[task resume];
}

接下来我们来看看,使用了AFNetworking

- (void)getArtistInfo:(NSString *)artistID accessToken:(NSString *)accessToken {NSString *urlString = [NSString stringWithFormat:@"https://api.spotify.com/v1/artists/%@", artistID];// 创建 AFHTTPSessionManager 实例AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];// 设置请求头[manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@", accessToken] forHTTPHeaderField:@"Authorization"];// 发起 GET 请求[manager GET:urlString parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {// 成功获取数据NSDictionary *json = (NSDictionary *)responseObject;Artist *art = [Artist yy_modelWithDictionary:json];NSLog(@"Artist Info: %@", json);NSLog(@"Artist Followers Total: %ld", (long)art.followersTotal);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {// 处理错误NSLog(@"%@", error.localizedDescription);}];
}

我们可以看到即使增加了请求头,在AFNetworking之中还是十分的方便的,我们只需要在manager之中的requestSerializer使用相关的方法设置它的请求头,再次调用GET的相关函数。

POST请求

学习完了如何使用AFN完成GET,接下来是网络请求不可或缺的POST请求的学习,下面我使用一个简单的POST函数来实现一个登陆注册的操作

- (void)loginWithUsername:(NSString *)username password:(NSString *)password {NSString *urlString = @"https://api.example.com/login";// 创建 AFHTTPSessionManager 实例AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];// 请求参数NSDictionary *parameters = @{@"username": username, @"password": password};// 发起 POST 请求[manager POST:urlString parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {// 成功获取响应数据NSLog(@"%@", responseObject);// 在这里可以解析响应数据,比如存储的Token} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {// 处理失败NSLog(@"%@", error.localizedDescription);}];
}

可以看到我们实现POST操作和GET操作本质上没有什么特别大的的区别,POST的请求只是讲包装后的字典发送到对应的URL地址,惊醒对应的验证。

使用POST操作上传图片

我们使用POST之中上传图片作为例子,模拟如何进文件的上传

#import <AFNetworking/AFNetworking.h>- (void)uploadImageWithURL:(NSString *)urlStringimageData:(NSData *)imageDataparameters:(NSDictionary *)parameterssuccessBlock:(void (^)(id responseObject))successBlockfailureBlock:(void (^)(NSError *error))failureBlock {// 创建请求管理器AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];// 设置请求的 `Content-Type` 为 `multipart/form-data`[manager POST:urlString parameters:parameters headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {// 将二进制图像数据添加到 `formData`[formData appendPartWithFileData:imageDataname:@"file" // 文件字段名,服务器接收的 keyfileName:@"image.jpg" // 文件名,可以随意mimeType:@"image/jpeg"]; // MIME 类型,取决于文件类型} progress:^(NSProgress * _Nonnull uploadProgress) {// 上传进度处理 (可选)NSLog(@"Upload Progress: %.2f%%", 100.0 * uploadProgress.fractionCompleted);} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {// 请求成功,处理服务器返回的数据NSLog(@"%@", responseObject);if (successBlock) {successBlock(responseObject);}} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {// 请求失败,处理错误NSLog(@"%@", error);if (failureBlock) {failureBlock(error);}}];
}

这里我们使用两个回调的block进行对应的成功和失败的操作,可以确保我们在获取到对应信息之后,再进行接下来的相关操作

NSString *url = @"https://example.com/upload";
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"exampleImage"], 0.9); // 将图片转成NSData格式 即二进制格式
NSDictionary *parameters = @{@"userId": @"12345", @"description": @"Profile Image"};[self uploadImageWithURL:url imageData:imageData parameters:parameters successBlock:^(id responseObject) {NSLog(@"Success response: %@", responseObject);
} failureBlock:^(NSError *error) {NSLog(@"Failed with error: %@", error.localizedDescription);
}];

对于这个方法**appendPartWithFileData:name:fileName:mimeType:**:

  • fileData: 你要上传的文件的二进制数据(如图片的 NSData)。
  • name: 服务器端接收文件的字段名,通常是 "file" 或自定义字段。
  • fileName: 上传时文件的名字,可以指定任何合适的文件名,比如 "image.jpg"
  • mimeType: 上传文件的 MIME 类型,比如 "image/jpeg""application/pdf"

要是是其他的文件,比如PDF或者MP3格式的,需要调整 fileNamemimeType。例如:

  • PDF: @"application/pdf"
  • MP3: @"audio/mpeg"

NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"profile.jpg"], 0.8);将图片文件转换为 JPEG 格式的二进制数据(NSData),CGFloat compressionQuality: 这是 JPEG 的压缩质量参数,范围是 0.01.0,其中 1.0 表示最高质量,0.0 表示最低质量(高压缩)。通常,0.70.9 的压缩比可以保持较好的图片质量,同时减少文件大小。

用单例进行网络申请

在进行网络申请的时候,我们可以使用一个AFN实现一个单例类,在项目中使用 AFNetworking 的单例进行网络请求,可以创建一个 AFHTTPSessionManager 的单例类。这有助于网络请求在整个应用中保持统一的配置,比如通用的请求头、超时时间等。这就可以用上我们先前的GCD之中的Once函数。

// NetworkManager.h
#import <AFNetworking/AFNetworking.h>@interface NetworkManager : AFHTTPSessionManager+ (instancetype)sharedManager;@end

.m文件

// NetworkManager.m
#import "NetworkManager.h"@implementation NetworkManager+ (instancetype)sharedManager {static NetworkManager *sharedManager = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{// 初始化 AFHTTPSessionManager 并进行一些全局配置sharedManager = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"https://api.yourserver.com/"]];// 例如,设置请求的超时时间sharedManager.requestSerializer.timeoutInterval = 30;// 可以设置请求的序列化格式(默认是JSON)sharedManager.requestSerializer = [AFJSONRequestSerializer serializer];// 可以设置响应的序列化格式(默认是JSON)sharedManager.responseSerializer = [AFJSONResponseSerializer serializer];});return sharedManager;
}@end

http://www.ppmy.cn/ops/127100.html

相关文章

旋转花键材质及运用场景

旋转花键的材质有很多种&#xff0c;其材质选择是一个涉及多方面因素的重要决策&#xff0c;‌主要取决于应用场景的具体要求&#xff0c;包括设备的运行环境、负载大小、运行速度以及所需的耐磨性和耐腐蚀性等因素。 1、碳钢&#xff1a;价格低廉、具有较好的韧性和耐磨性&…

传输层协议UDP详解

目录 一. 知识准备 1.1 传输层 1.2 重识端口号 二. UDP协议 三. UDP协议特点 一. 知识准备 1.1 传输层 前面已经讲过&#xff0c;HTTP协议是应用层协议&#xff0c;在此之前&#xff0c;我们短暂的认为HTTP是直接通过应用层与外界通信的。但是我们要知道&…

论新能源智能化电动车个性化(高定)产品对制造生产的影响

一、新能源智能化电动车高定体现模式 1.个性体现在品牌之间 在不同主机产产品上体现&#xff0c;例如国产新能源新势力在智能座舱、内饰配置&#xff08;冰箱、彩电、大沙发&#xff09;方面对于合资品牌的碾压&#xff0c;提供更多细分&#xff0c;功能拉满的车型。 2.个性化…

C++之“构造函数”

文章目录 类的默认成员函数构造函数 类的默认成员函数 默认成员函数就是我们没有在main函数里调用&#xff0c;但是编译器会自动生成的成员函数称为默认成员函数。 C由8个默认成员函数&#xff0c;我们暂时了解6个。 默认成员函数&#xff1a;构造函数&#xff0c;析构函数&a…

Flink On kubernetes

Apache Flink 是一个分布式流处理引擎&#xff0c;它提供了丰富且易用的API来处理有状态的流处理应用&#xff0c;并且在支持容错的前提下&#xff0c;高效、大规模的运行此类应用。通过支持事件时间&#xff08;event-time&#xff09;、计算状态&#xff08;state&#xff09…

【强化学习RL入门】基础概念和框架介绍(一):Stable Baseline3和gym的下载

前言 相信各位深度学习炼丹师都或多或少听过近几年很火的强化学习的内容&#xff0c;强化学习作为新时代的产物&#xff0c;在人工智能领域异军突起&#xff0c;被视为深度学习&#xff08;Deep Learning, DL&#xff09;的“下一代”替代品。然而&#xff0c;在许多实际应用中…

「撸一手好代码」设计模式之开闭原则

「撸一手好代码」设计模式之开闭原则 什么是开闭原则&#xff1f; 开闭原则&#xff08;Open-Closed Principle, OCP&#xff09;是指软件实体&#xff08;如类、模块、函数等&#xff09;应当对扩展开放&#xff0c;对修改关闭。这意味着软件系统的设计应当允许在不修改现有代…

Vue 文件类型声明

.vue后缀类型声明 我们在 main.ts 文件中引入其他vue文件的时候&#xff0c;是没有类型声明的&#xff0c;也就是说我们知道引入了一个vue文件&#xff0c;但是我们不知道这个文件是准备干嘛的。所以我们需要单独为这个加上一个类型的声明。如果说没有声明也没有报错的话&…