Moya网络框架
- 游戏开发
- 2025-09-07 17:09:01

Moya 网络框架
定义enum类型,有多种接口就定义多少种,然后实现TargetType协议
import Foundation //导入网络框架 import Moya enum DefaultService { //广告列表 case ads(position : Int) case sheets(size:Int) case sheetDetail(data: String) case register(data : User) } // MARK: - 实现TargetType协议 extension DefaultService:TargetType { //返回API地址 var baseURL: URL { return URL(string: Config.ENDPOINT)! } //返回每个请求的路径 var path: String { switch self { case.ads(_): return "v1/ads" case .sheets : return "v1/sheets" case .sheetDetail(let data): return "v1/sheets/\(data)" case .register(_) : return "v1/users" default: fatalError("error") } } //请求方式 var method: Moya.Method { switch self { case .register : return .post default: return .get } } var task: Moya.Task { switch self { case .ads(let position): return ParamUtil.urlRequestParamters(["position":position]) case .sheets(let size): return ParamUtil.urlRequestParamters(["size":size]) default : //不传递任何参数 return .requestPlain } } var headers: [String : String]? { var headers: Dictionary<String,String> = [:] return headers } }使用方法
let provider = MoyaProvider<DefaultService>() provider.request(.sheets(size: 10)) { result in print(result) switch result { case let .success(response) : let data = response.data let statusCode = response.statusCode let datastring = String(data: data,encoding: .utf8)! print(statusCode) print(datastring) case let .failure(error) : print(error) } }可以看到,最后返回的形式为字符串,不方便使用,所以需要进一步进行封装,将其转换为对象
使用RxSwift框架请求网络 //rxSwift 方式 provider.rx.request(.sheets(size: 10)) .debug("Request") .subscribe { event in switch event { case let .success(response) : print("hello ") let data = response.data let statusCode = response.statusCode let datastring = String(data: data,encoding: .utf8)! print(statusCode) print(datastring) if let r = SheetListResponse.deserialize(from: datastring){ print(r.status) print(r.data.data[0].title!) } case let .failure(error) : print(error) } }.disposed(by: rx.disposeBag) //释放相关资源,防止内存泄露 使用框架解析JSON数据使用第三方库HandyJSON
根据给出的JSON格式,建立相关的类即可
然后把字符串转换成相对应的格式即可
if let r = SheetListResponse.deserialize(from: datastring) 封装自动解析JSON功能对Observable进行拓展
// MARK: - 扩展Observable extension Observable{ /// 将字符串解析为对象 /// /// - Parameter type: 要转为的类 /// - Returns: 转换后的观察者对象 public func mapObject<T:HandyJSON>(_ type:T.Type) -> Observable<T> { map { data in //将参数尝试转为字符串 guard let dataString = data as? String else { //data不能转为字符串 throw IxueaError.objectMapping } guard let result = type.deserialize(from: dataString) else{ throw IxueaError.objectMapping } //解析成功 //返回解析后的对象 return result } } }在 Swift 中,map 是一种高阶函数,通常用于对集合(如数组、字典、可选值等)中的元素进行转换或映射。在你的代码中,map 用于将某个数据转换为期望的类型。
map 的基本作用:
map 会对序列中的每个元素执行一个闭包,然后返回一个新序列,其中每个元素都经过闭包的处理。
let numbers = [1, 2, 3] let doubledNumbers = numbers.map { $0 * 2 } // doubledNumbers == [2, 4, 6]在这个例子中,map 会遍历 numbers 数组中的每个元素,并将每个元素乘以 2,然后返回一个新的数组。
代码中 map 的使用:
代码中使用 map 似乎是在处理一些数据转换,具体是将某种类型的数据(data)尝试转为字符串类型,并解析成目标类型对象。详细讲解如下:
map { data in // 将参数尝试转为字符串 guard let dataString = data as? String else { // data 不能转为字符串 throw IxueaError.objectMapping } guard let result = type.deserialize(from: dataString) else { throw IxueaError.objectMapping } // 解析成功 // 返回解析后的对象 return result }分解讲解:
1. map { data in … }
• map 会对集合中的每个元素执行闭包中的代码,并返回一个新集合。这里的闭包是 data in { … },它接受集合中的每个元素作为输入(在这里是 data)。
• data 可能是一个原始数据,可以是任何类型,但在此代码中,它最终被尝试转换为 String 类型。
2. guard let dataString = data as? String else { throw IxueaError.objectMapping }
• 使用 guard let 尝试将 data 转换为 String 类型。如果转换失败(即 data 不是一个字符串),则会跳转到 else 语句,抛出错误(IxueaError.objectMapping),中断当前的操作并退出。
• guard let 语句是一种早期退出的方式,用来简化条件判断并在条件不满足时处理错误。
3. guard let result = type.deserialize(from: dataString) else { throw IxueaError.objectMapping }
• 假设 type 是一个类型,它提供了 deserialize(from:) 方法,用来将 dataString 字符串解析成目标类型的对象。
• 如果解析失败(即 deserialize 返回 nil),同样会抛出一个错误。deserialize 可能返回一个 nil,表示无法从字符串中成功解析出对象。
4. return result
• 如果 data 成功转换为字符串,并且字符串成功被解析为目标类型的对象,最终的 result 会被返回。这个 result 就是经过 map 处理后得到的新元素。
总结:
• map:遍历集合中的每个元素,并应用闭包中的代码,返回转换后的新集合。
• guard:用于提前退出函数,如果条件不成立则抛出错误(throw IxueaError.objectMapping)。
• deserialize:将字符串解析成目标类型,如果失败则抛出错误。
代码的核心目的是将原始数据转换为字符串,然后再将字符串解析为目标类型对象。如果过程中有任何失败的地方(如类型转换失败或解析失败),都会抛出错误并停止处理。
对网络部分进行封装为了解决JSON中相同类型对复用,所以将一些公共部分对类型写成一个类去继承,这样就避免了对于每一个JSON格式都需要再进行定义该类型。
同理,我们不可能对于每一个JSON去创建一个对应的类,所以使用范型,定义一些公共部分,每次传入该JSON应该属于什么类型即可。即定义了详情网络解析类,解析列表网络请求类
下一篇
三、Java中七大常用锁实战