iOS 网络请求: Alamofire 结合 ObjectMapper 实现自动解析

引言

在 iOS 开发中,网络请求是常见且致其重要的功能之一。从获取资料到上传数据,出色的网络请求框架能夠大大提升开发效率。

Alamofire 是一个极具人气的 Swift 网络请求框架,提供了便据的 API 以完成网络请求和响应处理。它支持多种请求类型,如 GET 和 POST,并且给予您便据的带容处理过滤器和返回数据解析的功能。

ObjectMapper 是一个强大的 Swift 数据映射工具,使用其提供的 Mappable 协议,可以将 JSON 数据自动映射到 Swift 模型中,大大简化解析代码和出错处理。

本文将介绍如何使用 Alamofire 和 ObjectMapper,完成 GET 和 POST 请求,并将返回数据自动解析为 Swift 模型。通过实战和代码示例,帮助您快速熟练这两种工具,从而提升开发效率。

Alamofire发起GET、POST请求

Alamofire为我们提供了十分简洁的数据请求方法,还可以根据数据的返回类型解析不同的响应体,我们以JSON格式为例。只需要设置请求地址、请求方式、请求参数、编码方式以及请求头。

GET请求

AF.request(url, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: endpoint.headers).responseJSON { (response) inswitch response.result {case .success:if let json = response.value as? [String: Any] {...} else {// 数据为空 或者格式不对let error = NSError(domain: "com.mw.network.error", code: MWNetworkDefine.clientErrorCode_dataFormat, userInfo: [NSLocalizedDescriptionKey: "数据为空或者格式不对"])}case .failure(let error):let mwError = MWNetError(error: error,isCanceled: error.isExplicitlyCancelledError)completion(nil, nil, mwError)}}

POST请求

AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: endpoint.headers).responseJSON { (response) inswitch response.result {case .success:if let json = response.value as? [String: Any] {....} else {// 数据为空 或者格式不对let error = NSError(domain: "com.mw.network.error", code: MWNetworkDefine.clientErrorCode_dataFormat, userInfo: [NSLocalizedDescriptionKey: "数据为空或者格式不对"])}case .failure(let error):let mwError = MWNetError(error: error,isCanceled: error.isExplicitlyCancelledError)mainThread(model: nil, data: nil, error: mwError, completion: completion)}}

ObjectMapper进行数据解析

使用ObjectMapper进行数据解析成模型时,需要模型遵循Mappable协议,并手动创建数据对应的键值映射。

假设有以下的json数据:

{"id": 123,"name": "John Doe","email": "john.doe@example.com"
}

那我们需要可以创建一个对应的数据模型:

import ObjectMapperclass User: Mappable {var id: Int?var name: String?var email: String?required init?(map: Map) {}func mapping(map: Map) {id    <- map["id"]name  <- map["name"]email <- map["email"]}
}

然后借助Mapper实现解析:

func parseUserData(json: [String: Any]) {if let user = Mapper<User>().map(JSON: json) {print("User ID: \(user.id ?? 0)")print("Name: \(user.name ?? "No Name")")print("Email: \(user.email ?? "No Email")")} else {print("Failed to parse user data")}
}// 示例调用
let jsonData: [String: Any] = ["id": 123,"name": "John Doe","email": "john.doe@example.com"
]parseUserData(json: jsonData)

Alamofire结合ObjectMapper实现接口数据自动解析

而在实际的项目开发中往往我们并不会直接使用Alamofire进行网络的请求,而是会进一步封装增加一层,在这一层中呢我们可以设置一些公共参数,公共请求头,请求加密处理,服务端环境切换等等等等工作,包括数据的处理和自动解析当然也可以在这一层来进行。

以我们当前的项目为例,为了处理网络的请求专门创建了一个名为MWNetworkHelper的类,它负责文件的上传、文件的下载、非加密的GET请求,非加密的POST请求,加密的GET请求、加密的POST请求,以及请求后的数据处理和错误处理。

接下来我们就以非加密的POST请求为例来分析Alamofire结合ObjectMapper实现接口数据自动解析。

项目中的所有请求通过MWNetworkHelper的类方法发送:

public class func request<T: Mappable>(endpoint: MWAPIProtocol, parameters: [String: Any]?,modelType:T.Type? = MWNetEmptyData.self, completion: ((_ model:T?,_ data:Any?, MWNetError?) -> Void)?) -> DataRequest?

该方法的具体实现如下:

    /// 发起请求/// - Parameters:/// - endpoint: 请求地址,枚举/// - parameters: 请求参数/// - completion: 请求完成回调/// - T: 返回数据模型/// - return: 请求@discardableResultpublic class func request<T: Mappable>(endpoint: MWAPIProtocol, parameters: [String: Any]?,modelType:T.Type? = MWNetEmptyData.self, completion: ((_ model:T?,_ data:Any?, MWNetError?) -> Void)?) -> DataRequest? {let completion = completion ?? {_,_,_ in }// 如果是断网状态直接返回if !MWNetworkManager.shared.isReachable {let error = NSError(domain: "com.mw.network.error", code: MWNetworkDefine.clientErrorCode_noNetwork, userInfo: [NSLocalizedDescriptionKey: "网络不可用"])let mwError = MWNetError(error: error,isCanceled: false)MWToast.showToast("网络不可用")mainThread(model: nil, data: nil, error: mwError, completion: completion)return nil}if let encryEndpoint = endpoint as? MWAPIEncryEndpoint{return requestEncrypt(endpoint: encryEndpoint, parameters: parameters, modelType: modelType, completion: completion)} else if let normalEndpoint = endpoint as? MWAPINormalEndpoint {return requestNormal(endpoint: normalEndpoint, parameters: parameters, modelType: modelType, completion: completion)} else {fatalError("endpoint is not MWAPIProtocol")}}
  1. 该方法首先判断了网络状态,如果处于断网状态直接回调回error数据。
  2. 接下来根据枚举所属的类判断发起的是加密请求还是非加密请求。

加密请求和非加密请求都还会再次分割为GET请求和POST的请求,我们直接过渡到非加密的POST请求。

    /// 发起非加密的POST请求/// - Parameters:/// - endpoint: 请求地址,枚举/// - parameters: 请求参数/// - completion: 请求完成回调/// - T: 返回数据模型/// - return: 请求@discardableResultpublic class func requestNormalPOST<T: Mappable>(endpoint: MWAPINormalEndpoint, parameters: [String: Any]?, modelType:T.Type? = MWNetEmptyData.self, completion: @escaping (_ model:T?,_ data:Any?, MWNetError?) -> Void) -> DataRequest {MWLogHelper.debug("非加密POST=请求地址:\(endpoint.domain + endpoint.path) 请求参数:\(String(describing: parameters))", context: "Network")let url = endpoint.domain + endpoint.pathreturn AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: endpoint.headers).responseJSON { (response) inswitch response.result {case .success:if let json = response.value as? [String: Any] {dealRequestJsonData(endpoint: endpoint, data: json, completion: completion)} else {// 数据为空 或者格式不对let error = NSError(domain: "com.mw.network.error", code: MWNetworkDefine.clientErrorCode_dataFormat, userInfo: [NSLocalizedDescriptionKey: "数据为空或者格式不对"])let mwError = MWNetError(error: error,isCanceled: false)mainThread(model: nil, data: nil, error: mwError, completion: completion)}case .failure(let error):let mwError = MWNetError(error: error,isCanceled: error.isExplicitlyCancelledError)mainThread(model: nil, data: nil, error: mwError, completion: completion)}}}
  1. 利用Swift的特性我们创建了一个泛型,通过T:Mappable指定了返回数据模型必须遵循ObjectMapper的Mappable协议,确保可以进行JSON映射,灵活支持不同的返回类型。
  2. MWAPINormalEndpoint是一个非加密请求的枚举,枚举内包含了很多内容包括请求的域名或根据环境进行切换,包括具体的请求接口以及公共请求头等等信息。
  3. 对于一个成功的请求,调用dealRequestJsonData方法开始处理数据。
  4. 而对于一个失败的请求,我们直接回调回error信息。

对于数据处理的方法dealRequestJsonData,由于项目庞大的原因,它仍然包含了很多内容,但是我们可以把重点直接集中到简单的部分:

    /// 处理数据/// - Parameters:/// - data: 数据/// - completion: 完成回调/// - T: 返回数据模型private class func dealRequestJsonData<T: Mappable>(endpoint: MWAPIProtocol,data:[String:Any],modelType:T.Type? = nil,completion: @escaping (_ model:T?,_ data:Any?, MWNetError?) -> Void) {var data = data// 如果是加密数据....if endpoint.isDirectParse {// 错误结果if let code = data["code"] as? Int {...return}// 直接解析let model = Mapper<T>().map(JSON: data)mainThread(model: model, data: data, error: nil, completion: completion)} else {....}}/// 主线程回调/// - Parameters:/// - modelType: 数据模型类型/// - model: 数据模型/// - data: 数据/// - error: 错误/// - completion: 完成回调private class func mainThread<T: Mappable>(modelType:T.Type? = nil,model:T?,data:Any?,error:MWNetError?,completion: @escaping (_ model:T?,_ data:Any?, MWNetError?) -> Void) {DispatchQueue.main.async {completion(model, data, error)}}
  1. 因为服务端并不一定会只返回一种结构的数据格式,我们只考虑直接解析这一种。​​​​​​​
  2. 直接通过let model = Mapper<T>().map(JSON: data)获取到我们需要的数据模型。
  3. 在主线程中回调回数据。

结语

在现代 iOS 应用开发中,处理网络请求和数据解析是一项基础但极具挑战的任务。本文通过 Alamofire 和 ObjectMapper 的结合,展示了如何构建灵活且高效的网络请求与数据解析架构。从发起请求到解析数据,再到错误处理的全流程,我们看到了这两种工具如何相辅相成,极大提升了开发效率。

然而,开发并非一成不变,实际应用场景中,可能会涉及到更多复杂的需求,例如分页加载、文件上传、错误重试等。希望本篇内容为你的项目提供启发,也欢迎你探索和扩展 Alamofire 与 ObjectMapper 的更多潜力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/68771.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【0397】Postgres内核 checkpoint process ⑦ 获取 delaying checkpoint VXIDs(delayChkpt)

1. Top-level transactions 顶级事务(Top-level transactions)通过由 PGPROC 字段 backendId 和 lxid 组成的 VirtualTransactionIDs 来标识。对于已准备的事务,LocalTransactionId 是一个普通的 XID。这些在短期内保证唯一,但在数据库重启或 XID 滚转后会被重新使用;因此…

68,[8] BUUCTF WEB [RoarCTF 2019]Simple Upload(未写完)

<?php // 声明命名空间&#xff0c;遵循 PSR-4 自动加载规范&#xff0c;命名空间为 Home\Controller namespace Home\Controller;// 导入 Think\Controller 类&#xff0c;以便扩展该类 use Think\Controller;// 定义 IndexController 类&#xff0c;继承自 Think\Control…

IntelliJ IDEA 2023.3 中配置 Spring Boot 项目的热加载

IntelliJ IDEA 2023.3 中配置 Spring Boot 项目的热加载 在 IntelliJ IDEA 2023.3 中配置 Spring Boot 项目的热加载&#xff0c;可以让你在不重启应用的情况下看到代码修改的效果。以下是详细的配置步骤&#xff1a; 添加 spring-boot-devtools 依赖 在 pom.xml 文件中添加 …

使用HTML5 Canvas 实现呼吸粒子球动画效果的原理

在网页开发领域&#xff0c;动画效果能够极大地提升用户体验&#xff0c;让页面变得更加生动有趣。今天&#xff0c;我们深入剖析一个基于 HTML5 Canvas 的 3D 粒子动画 —— 呼吸粒子球。通过详细解读其代码实现&#xff0c;我们将全面了解如何运用 HTML5 的强大功能构建出如此…

【C++】引用(上)

1、引用的基本使用 作用&#xff1a;给变量起别名 语法&#xff1a;数据类型&#xff08;该数据类型要与原名的数据类型一致&#xff09; &别名原名&#xff1b; 示例&#xff1a; #include<iostream> using namespace std; int main() {int a 10;int& …

JDBC实验测试

一、语言和环境 实现语言&#xff1a;Java。 环境要求&#xff1a;IDEA2023.3、JDK 17 、MySQL8.0、Navicat 16 for MySQL。 二、技术要求 该系统采用 SWING 技术配合 JDBC 使用 JAVA 编程语言完成桌面应用开发。 三、功能要求 某电商公司为了方便客服查看用户的订单信…

外包公司名单一览表(成都)

大家好&#xff0c;我是苍何。 之前写了一篇武汉的外包公司名单&#xff0c;评论区做了个简单统计&#xff0c;很多人说&#xff0c;在外包的日子很煎熬&#xff0c;不再想去了。 有小伙伴留言说有些外包会强制离职&#xff0c;不行就转岗&#xff0c;让人极度没有安全感。 这…

一些硬件知识【2025/1/21】

小米2K摄像头拆解&#xff1a; 这种小转接板空余部分一般全部打上过孔&#xff1a; 摄像头下面的SENSOR,这一部分才是摄像头的核心&#xff1a; 干硬件多久跳槽一次比较合适&#xff1f;3年跳一次可以吗&#xff1f; eMCC存储芯片外面那一圈焊盘是做什么用的&#xff1f; 没有…

WPF实战案例 | C# WPF实现计算器源码

WPF实战案例 | C# WPF实现计算器源码 一、设计来源计算器应用程序讲解1.1 主界面1.2 计算界面 二、效果和源码2.1 界面设计&#xff08;XAML&#xff09;2.2 代码逻辑&#xff08;C#&#xff09;2.3 实现步骤总结 源码下载更多优质源码分享 作者&#xff1a;xcLeigh 文章地址&a…

如何在 Pytest 中使用命令行界面和标记运行测试

关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理&#xff0c;构建成功的基石 在自动化测试工作之前&#xff0c;你应该知道的10条建议 在自动化测试中&#xff0c;重要的不是工具 在前文你已经初步尝试编写了代码和单元测试&#xff0c;并且想要确保它能正常运行。…

【HBuilderX 中 Git 的使用】

目录&#xff1a; 一&#xff1a;安装必要的版本控制工具二&#xff1a;把Github上的项目克隆到本地三&#xff1a;将本地的项目上传到Github上 一&#xff1a;安装必要的版本控制工具 1️⃣ 安装 TortoiseGit 工具&#xff0c;下载地址&#xff1a;https://tortoisegit.org/do…

浅谈 JVM

JVM 内存划分 JVM 内存划分为 四个区域&#xff0c;分别为 程序计数器、元数据区、栈、堆 程序计数器是记录当前指令执行到哪个地址 元数据区存储存储的是当前类加载好的数据&#xff0c;包括常量池和类对象的信息&#xff0c;.java 编译之后产生 .class 文件&#xff0c;运…

嵌入式学习(24)-STM32F407 Hal库IAP升级

一、概述 IAP是用户自己的程序在运行过程中对 User Flash的部分区域进行烧写&#xff0c;目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。 通常 实现 IAP功能时&#xff0c;即用户程序运行中作自身的更新操作&#xff0c;需要在设计固件程序…

头歌实训作业 算法设计与分析-贪心算法(第1关:部分背包问题)

部分背包问题 设有编号为1、2、…、n的n个物品&#xff0c;它们的重量分别为w1、w2、…、wn&#xff0c;价值分别为v1、v2、…、vn&#xff0c;其中wi、vi&#xff08;1≤i≤n&#xff09;均为正数。 有一个背包可以携带的最大重量不超过W。求解目标&#xff1a;在不超过背包负…

第17章:Python TDD回顾与总结货币类开发

写在前面 这本书是我们老板推荐过的&#xff0c;我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后&#xff0c;我突然思考&#xff0c;对于测试开发工程师来说&#xff0c;什么才更有价值呢&#xff1f;如何让 AI 工具更好地辅助自己写代码&#xff0c;或许…

MyBatis 注解开发详解

MyBatis 注解开发详解 MyBatis 支持使用注解来进行数据库操作。注解方式将 SQL 语句直接写在 Java 接口中&#xff0c;通过注解来完成 CRUD&#xff08;增删改查&#xff09;操作&#xff0c;省去了使用 XML 配置的繁琐步骤。这种方式适合简单项目或快速原型开发&#xff0c;因…

OpenCV简介、OpenCV安装

OpenCV简介、OpenCV安装 本文目录&#xff1a; 零、时光宝盒 一、OpenCV简介 二、OpenCV图像处理基础知识 三、OpenCV-Python环境安装 2.1、纯python环境下安装OpenCV 2.2、Anaconda管理环境下安装 OpenCV 四、如何用OpenCV 中进行读取展示图像 五、OpenCV读取图像、显…

使用Chrome和Selenium实现对Superset等私域网站的截图

最近遇到了一个问题&#xff0c;因为一些原因&#xff0c;我搭建的一个 Superset 的 Report 功能由于节假日期间不好控制邮件的发送&#xff0c;所以急需一个方案来替换掉 Superset 的 Report 功能 首先我们需要 Chrome 浏览器和 Chrome Driver&#xff0c;这是执行数据抓取的…

react19新API之use()用法总结

React use() Hook 使用指南 概述 use() 是 React 19 引入的新 Hook&#xff0c;它允许你在组件内部直接使用 Promise、Context 和其他可订阅的值。它是一个更通用的数据获取和订阅机制。 基本语法 const value use(resource);主要用途 1. Promise 处理 function UserDet…

Netty到底是什么,解决了什么问题,Netty为什么会火,Netty有什么特性

Netty是一个高性能、异步事件驱动的网络应用框架&#xff0c;它基于Java NIO&#xff08;New Input/Output&#xff09;开发&#xff0c;并对Java NIO进行了封装和扩展。Netty的特性及其解决的问题可以归纳如下&#xff1a; 一、Netty的主要特性 优雅的设计&#xff1a;Netty…