在OC开发中网络请求通常都使用AFNetworking,在Swift虽然也可以使用,但是推荐使用Swift语法实现的网络请求库Alamofire
通常大家会对请求库进行一次或多次封装,方便维护,我也不另外。刚开始参考了很多文章,最终决定使用Alamofire + Moya + SwiftyJSON 实现网络请求工具类和API管理类
本篇末尾介绍另一种通过链式封装Alamofire的实现方式

GitHub Demo 地址

Alamofire是一个使用Swift开发的网络请求库,其开发团队是AFNetworking的原团队。它语法简洁,采用链式编程的思想,使用起来是相当的舒服。本质是基于NSURLSession进行封装。
Moya是对Alamofire的再次封装。
SwiftyJSON是数据解析

github地址:

Alamofire
Moya
SwiftyJSON

pods引用:

pod 'Alamofire', '4.9.1'
pod 'Moya', '13.0.1'
pod 'SwiftyJSON', '5.0.1'

首先需要创建3个Swift文件:
一个是网络请求工具类:JhHttpTool.swift
一个Moya配置文件:MoyaConfig.swift
一个API管理文件:APIManager.swift

接下来直接上代码

JhHttpTool

//
//  JhHttpTool.swift
//  JhSwiftDemo
//
//  Created by Jh on 2021/12/28.
//  网络请求工具类:Alamofire + Moya + SwiftyJSON
import Foundation
import Moya
import SwiftyJSONpublic class JhHttpTool {/// 使用Moya的请求封装////// - Parameters:///   - target: 请求API,TargetType里的枚举值///   - success: 成功的回调///   - error: 连接服务器成功但是数据获取失败///   - failure: 连接服务器失败public class func request<T: TargetType>(_ target: T, success: @escaping((Any) -> Void), failure: ((Int?, String) ->Void)?) {let provider = MoyaProvider<T>(plugins: [RequestHandlingPlugin(),//            networkLoggerPlugin])provider.request(target) { result inswitch result {case let .success(response)://                let json = try? response.mapString()//                let responseObject = try? response.mapJSON()//                JhLog( responseObject ?? "" );do {// *********** 这里可以统一处理错误码,弹出提示信息 ***********let resObject = try? response.mapJSON()let responseObject = JSON(resObject ?? "")let code = responseObject["code"].intValuelet msg = String(describing: responseObject["msg"])switch (code) {case 200 :// 数据返回正确success(responseObject)case 401:// 请重新登录failure!(code,msg)alertLogin(msg)default:// 其他错误failureHandle(failure: failure, stateCode: code, message: msg)}}case let .failure(error):let statusCode = error.response?.statusCode ?? 1000let message = "请求出错,错误码:" + String(statusCode)JhAllLog(message)failureHandle(failure: failure, stateCode: statusCode, message: error.errorDescription ?? message)}}// 错误处理 - 弹出错误信息func failureHandle(failure: ((Int?, String) ->Void)? , stateCode: Int?, message: String) {Alert.show(type: .error, text: message)failure?(stateCode ,message)}// 登录弹窗 - 弹出是否需要登录的窗口func alertLogin(_ title: String?) {// TODO: 跳转到登录页的操作:}}// MARK: - 打印日志//    static let networkLoggerPlugin = NetworkLoggerPlugin(verbose: true, cURL: true, requestDataFormatter: { data -> String in//        return String(data: data, encoding: .utf8) ?? ""//    }) { data -> (Data) in//        do {//            let dataAsJSON = try JSONSerialization.jsonObject(with: data)//            let prettyData =  try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)//            return prettyData//        } catch {//            return data//        }//    }
}

MoyaConfig

//
//  JhHttpRequest.swift
//  JhSwiftDemo
//
//  Created by Jh on 2022/2/10.
//  Moya 配置文件
import Foundation
import Moya// MARK: - 1、2需要根据项目进行更改
/**1、配置TargetType协议可以一次性处理的参数- Todo: 根据自己的需要更改,不能统一处理的移除下面的代码,并在APIManager中实现**/
public extension TargetType {//    // 放到APIManager中了
//    var baseURL: URL {//        return URL(string: "http://xxxxx")!
//    }var headers: [String : String]? {return nil}var sampleData: Data {return "{}".data(using: String.Encoding.utf8)!}
}/**2、公共参数- Todo: 配置公共参数,例如所有接口都需要传token,version,time等,就可以在这里统一处理- Note: 接口传参时可以覆盖公共参数。下面的代码只需要更改 【private var commonParams: [String: Any]?】**/
extension URLRequest {//TODO:处理公共参数private var commonParams: [String: Any]? {//所有接口的公共参数添加在这里:let header = ["Content-Type": "application/x-www-form-urlencoded","systemType": "iOS","version": "1.0.0","token": getToken(),]return header// 如果不需要传空//        return nil}private func getToken() -> String {return "1"}
}//下面的代码不更改
class RequestHandlingPlugin: PluginType {public func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {var mutateableRequest = requestreturn mutateableRequest.appendCommonParams();}
}//下面的代码不更改
extension URLRequest {mutating func appendCommonParams() -> URLRequest {let request = try? encoded(parameters: commonParams, parameterEncoding: URLEncoding(destination: .queryString))assert(request != nil, "append common params failed, please check common params value")return request!}func encoded(parameters: [String: Any]?, parameterEncoding: ParameterEncoding) throws -> URLRequest {do {return try parameterEncoding.encode(self, with: parameters)} catch {throw MoyaError.parameterEncoding(error)}}
}

APIManager

//
//  APIManager.swift
//  JhSwiftDemo
//
//  Created by Jh on 2021/12/28.
//  接口管理
import Foundation
import Moya/// 基础域名
let kBaseURL = "https://www.fastmock.site/mock/1010b262a743f0b06c565c7a31ee9739/root"enum  API {case login(params:Dictionary<String,Any>)// 获取分页数据case getPageList(_ page:Int)// 获取分组分页数据case getGroupPageList(page:Int)// 获取联系人数据case getContact// 获取微信运行排行榜case getWxMotionTops// 获取固定数据case getSimpleArrDic///其他接口...case other1(p1: String, p2: Int, p3: String, p4: String)case other2}// MARK: - 补全【MoyaConfig 3:配置TargetType协议可以一次性处理的参数】中没有处理的参数
extension API: TargetType {//0. 基础域名,整个项目只用一个,可以写在MoyaConfig中var baseURL: URL {switch self {case .login:return URL(string:kBaseURL)!default:return URL(string:kBaseURL)!}}//1. 每个接口的相对路径//请求时的绝对路径是   baseURL + pathvar path: String {switch self {case .login:return "/login"case .getPageList:return "/mock/pages"case .getGroupPageList:return "/mock/groupPages"case .getContact:return "/mock/contacts"case .getWxMotionTops:return "/mock/wxMotionTops"case .getSimpleArrDic:return "/getSimpleArrDic"case let .other1(p1, p2, _, _):return "/list?id=\(p1)&page=\(p2)"case .other2:return ""}}//2. 每个接口要使用的请求方式var method: Moya.Method {switch self {case.getPageList,.getGroupPageList,.other1,.other2:return .getcase.getContact,.getWxMotionTops,.getSimpleArrDic,.login:return .post}}//3. Task是一个枚举值,根据后台需要的数据,选择不同的http task。var task: Task {var params: [String: Any] = [:]switch self {case .login:return .requestPlaincase let .getPageList(page):params["page"] = pageparams["limit"] = 15params["maxCount"] = 100case let .other1(_, _, p3, p4):params["p3"] = p3params["p4"] = p4default://不需要传参数的接口走这里return .requestPlain}return .requestParameters(parameters: params, encoding: URLEncoding.default)}}

使用

// Alamofire + Moya + SwiftyJSON
JhHttpTool.request(API.getPageList(1)) {[weak self] json inself?.mTextView.text = String(describing: JSON(json))JhAllLog(JSON(json))
} failure: {code, msg inJhLog("code : \(code!)")JhLog("message : \(msg)")
}

链式封装Alamofire

链式封装,API可以直接通过一个文件进行管理,里面只放url路径

//
//  JhRequest.swift
//  JhSwiftDemo
//
//  Created by Jh on 2021/12/28.
//  链式网络请求工具类:Alamofire + SwiftyJSON
import Foundation
import Alamofire
import SwiftyJSONenum HttpRequestType {case getcase post
}public let JhRequest = NetworkKit.shared// Networkkit属性设置
public class NetworkKit {public static let shared = NetworkKit()typealias SuccessHandlerType = ((JSON) -> Void)typealias FailureHandlerType = ((Int?, String) ->Void)private var requestType: HttpRequestType = .post//请求类型private var url: String?    // URLprivate var params: [String: Any]?  // 参数private var success: SuccessHandlerType?    // 成功的回调private var failure: FailureHandlerType?    // 失败的回调private var httpRequest: Request?}// NetworkKit属性的设置
extension NetworkKit{/// 设置urlfunc url(_ url: String?) -> Self {self.url = urlreturn self}/// 设置post/get 默认postfunc requestType(_ type:HttpRequestType) -> Self {self.requestType = typereturn self}/// 设置参数func params(_ params: [String: Any]?) -> Self {self.params = paramsreturn self}/// 成功的回调func success(_ handler: @escaping SuccessHandlerType) -> Self {self.success = handlerreturn self}///失败的回调func failure(handler: @escaping FailureHandlerType) -> Self {self.failure = handlerreturn self}}// NetworkKit请求相关
extension NetworkKit{/// 发起请求 设置好相关参数后再调用func request() -> Void {var dataRequest: DataRequest?   // alamofire请求后的返回值// 发起请求if let URLString = url {ProgressHUD.show()let method = requestType == .get ? HTTPMethod.get : HTTPMethod.postdataRequest =  Alamofire.request(URLString, method: method, parameters: params)httpRequest = dataRequest}dataRequest?.responseJSON {(response) inProgressHUD.hide()switch response.result {case let .success(response):do {// *********** 这里可以统一处理错误码,弹出提示信息 ***********let responseObject = JSON(response)let code = responseObject["code"].intValuelet msg = String(describing: responseObject["msg"])switch (code) {case 200 :// 数据返回正确self.success?(responseObject)case 401:// 请重新登录self.failure?(code,msg)alertLogin(msg)default:// 其他错误failureHandle(failure: self.failure, stateCode: code, message: msg)}}case let .failure(error):failureHandle(failure: self.failure, stateCode: nil, message: error.localizedDescription)}}// 错误处理 - 弹出错误信息func failureHandle(failure: FailureHandlerType? , stateCode: Int?, message: String) {Alert.show(type: .error, text: message)failure?(stateCode ,message)}// 登录弹窗 - 弹出是否需要登录的窗口func alertLogin(_ title: String?) {// TODO: 跳转到登录页的操作:}}// 取消请求func cancel() {httpRequest?.cancel()}}

使用

 // 链式网络请求:Alamofire + SwiftyJSONlet url = kBaseURL + "/getSimpleArrDic"JhRequest.url(url).params([:]).requestType(.post).success { res inJhLog(" ========链式网络请求======== ")JhAllLog(res)JhAllLog(res["code"])}.failure { code, msg inJhLog("code : \(code!)")JhLog("message : \(msg)")}.request()

Swift -《从0到1 - 5》:封装网络请求工具类(Alamofire + Moya + SwiftyJSON)和链式封装相关推荐

  1. 基于HttpURLConnection 网络请求工具类的封装

    HttpUtils: /*** Created by xiaoyehai on 2018/5/21 0021.*/public class HttpUtils {//线程池private static ...

  2. java okhttp3 工具类,Retrofit+okhttp+Rxjava网络请求工具类

    1.BaseApis接口封装请求方式 package com.example.wdshop.network; import java.util.Map; import okhttp3.Response ...

  3. go语言封装http请求工具类(访问外部接口)

    代码 // example: http://host:port/uri/?param1=1&param2=2 func Get(reqUrl string, jsonParams interf ...

  4. uniapp 封装网络请求

    文章目录 一.前端 1. 封装网络请求 2. 封装模块请求方法 二.后端 2.1. 返回对象 2.2. 热搜接口 三.微信模拟请求 3.1. Network 3.2. Console 一.前端 1. ...

  5. 封装网络请求 - iOS网络篇

    一.简单说明 1.分析项目对网路请求(AFN框架)的依赖 项目中,多个控制器都使用了AFN框架发送网络请求,如果AFN2.0存在重大BUg,或者是升级至3.0版本,那么对于整个项目都是及其危险的,所有 ...

  6. afn访问本地html,Swift利用AFN实现封装网络请求详解

    前言 相信大家都知道,我们一般在一个项目中,网络请求都封装成一个单例,以确保整个项目的网络请求 Session 是同一个. 单例模式定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供,下面话不 ...

  7. 微信小程序教学第二章(含视频):小程序中级实战教程之预备篇 - 封装网络请求及 mock 数据...

    § 封装网络请求及 mock 数据 本文配套视频地址: v.qq.com/x/page/i055- 开始前请把 ch2-3 分支中的 code/ 目录导入微信开发工具 上一节中,我们对 index.j ...

  8. 小程序中封装ajax请求,如何在微信小程序中封装网络请求

    如何在微信小程序中封装网络请求 发布时间:2021-05-11 16:59:36 来源:亿速云 阅读:95 作者:Leah 这期内容当中小编将会给大家带来有关如何在微信小程序中封装网络请求,文章内容丰 ...

  9. App 组件化/模块化之路——如何封装网络请求框架

    App 组件化/模块化之路--如何封装网络请求框架 在 App 开发中网络请求是每个开发者必备的开发库,也出现了许多优秀开源的网络请求库.例如 okhttp retrofit android-asyn ...

  10. Android中使用Kotlin协程代替RxJava封装网络请求

    现在的Android项目普遍使用Retrofit+RxJava的组合实现网络接口请求与数据的展现.这一功能通过Kotlin语言的协程功能也可以很方便的实现. 相比较而言,RxJava功能过于强大,如果 ...

最新文章

  1. 某天没有数据能查出来0数量_用Excel对纽约市出租车费数据探索性分析
  2. Android之Menu动态改变文字
  3. 【主席树】可持久化数组(金牌导航 可持久化数据结构-3)
  4. Gensee移动SDK之(一)结构组成
  5. 什么叫诚实_李现自爆平常最爱看小姐姐!IG按赞被抓包 网友赞:诚实
  6. Objc Runtime在项目中该怎么用
  7. jQuery判断checked的三种方法
  8. Android播放音频的两种方式
  9. C++ 标准模板库STL
  10. 新装的台式机新装WIN7系统启动时卡在开机动画如何解决?
  11. 自制Flash电子相册
  12. 利用python中的pygame模块开发fc坦克大战(可自定义地图,包括部分素材)
  13. Python 函数的嵌套
  14. 【MATLAB】MATLAB数值计算
  15. 汕头大学计算机专业就业,汕头大学毕业生最后怎样了?17%进入世界和中国500强,月薪5185元...
  16. LAMP虚拟主机架设论坛
  17. 【白皮书】以太坊 (Ethereum ):下一代智能合约和去中心化应用平台
  18. CS5213芯片|HDMI to VGA转换头芯片资料分享
  19. 【机器学习】Adaboost
  20. 基于React全家桶开发「网易云音乐PC」项目实战(三)

热门文章

  1. 即时通讯源码php开源版下载附安装教程+演示
  2. 华为杯2020-2021年数学建模大赛题目分享
  3. JAVA实现SHA256算法
  4. jdbc处理银行转账事务
  5. 计算机桌面如何分区,笔记本怎么分区
  6. AppScan介绍和安装
  7. Tableau 发布到tableau online错误
  8. Python基于协同过滤算法的电影推荐系统设计与实现
  9. [需求管理-9]:需求规格说明书SRS
  10. Eclipse 最佳字体 推荐