iOS开发中简单界面用一个接口请求可能就达到效果了, 但是对于级联列表,或者表单这类界面, 一般都会有多个接口请求,而且会有 Post Get 上传等多项需求 .
封装 MapModel 方法
让每个网络请求都走这个通道统一返回处理后的json 结果
1 2 3 4 5 6 7 8 9 10 11 12
// Send request provider.request(.login(userAccount: "18516635543", password: "1234565")) { (response) in switch response { case .success(let resp): let baseDataResult =self.mapModel(resp: resp) // interface use the model case .failure(_): print("网络异常, 请检查") return } }
funcmapModel(resp: Response) -> MoyaResult<MyServiceModel> { // 1.过滤状态码 guardlet_=try? resp.filterSuccessfulStatusCodes() else { return .failure(resp.statusCode, "服务器访问失败") } // 下面就是服务器返回的数据的问题了 // 2.解析 json // 转换成 jsonString // Setting the NSJSONWritingPrettyPrinted option will generate JSON with whitespace designed to make the output more readable. // the resulting data is a encoded in UTF-8. // Setting the NSJSONReadingMutableLeaves option will make the parser generate mutable NSString objects. guardlet jsonObj =try?JSONSerialization.jsonObject(with: resp.data, options: JSONSerialization.ReadingOptions.mutableLeaves), let jsonData =try?JSONSerialization.data(withJSONObject: jsonObj, options: JSONSerialization.WritingOptions.prettyPrinted), let jsonString =String(data: jsonData, encoding: String.Encoding.utf8) else{ print("数据无效") return .failure(-1, "数据无效") } // 打印 json 字符串 print(jsonString)
// 3.json 转 model guardlet base =JSONDeserializer<BaseData<MyServiceModel>>.deserializeFrom(json: jsonString) else { return .failure(-1, "数据无效") } /* 转换数据格式分为两种: 1. 无数据,只是表示成功或者失败状态 2. 有数据,返回 0.model 1.只有状态码,和描述字符串 */ // 1. No model data, only status information if base.errcode ==0 { // status success ; exam: submit success, download success; no model data to handle. // valid model data success iflet data = base.data { return .success(data) } return .failure(-1, "数据无效") }else { // return valid data, but data is other status return .failure(base.errcode, base.errmsg) } }
看 json 转 model 代码
1 2 3 4
// 3.json 转 model guardlet base =JSONDeserializer<BaseData<MyServiceModel>>.deserializeFrom(json: jsonString) else { return .failure(-1, "数据无效") }
这里的 BaseData 就涵盖了后台给的 json 格式
1 2 3 4 5 6
structBaseData<MyserviceMode>: HandyJSON{ // 根据公司后台返回格式,写一个基础数据模型 var errcode: Int=-1 var errmsg: String=NSLocalizedString("Network_errorCode_null", comment:"") var data: MyserviceMode? =nil }
// Simulate a network request let provider =MoyaProvider<MyServiceTarget>.appearance()
// Send request provider.request(.login(userAccount: "18516635543", password: "1234565")) { (response) in switch response { case .success(let resp): let result =self.mapModel(resp: resp) switch result { case .success(let md): nameLabel.text = md.name ageLabel.text = md.age case .failure(_ , let errmsg): print("后台返回错误信息:\(errmsg)") } case .failure(let error): print("网络异常, u 请检查") } }
// 自定义一个接收返回值的枚举,处理有数据状态下数据的处理 publicenumMoyaResult<T> { case success(T) case failure(Int,String) }
根据上面的 MyServiceModel 替换成了 T 作用是是什么呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// Simulate a network request let provider =MoyaProvider<MyServiceTarget>.appearance() // Send request provider.request(.login(userAccount: "18516635543", password: "1234565")) { (response) in switch response { case .success(let resp): let result =self.mapModel(resp: resp) switch result { case .success(let md): nameLabel.text = md.name ageLabel.text = md.age case .failure(_ , let errmsg): print("后台返回错误信息:\(errmsg)") } case .failure(let error): print("网络异常, u 请检查") } }
这里 T 就代表传进来的 Model 类型, 用处就是如上代码, 接口返回直接拿到 MyServiceModel 给界面控件赋值,改成泛型就能继续再向上传递, 通过学习 Moya 的方式, 包装一层 MoyaResult<T> 内部枚举值有 success, failure, 将 T 也就是Model,不同数据二次传递到泛型接口外面, 这样就能达到,不同界面调用这个request 方法, 都能拿到转成不同 Model 返回出来的目的.
上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
structGenericApi<Target: TargetType> {
let provider =MoyaProvider<Target>.appearance()
funcrequest<ModelT>(target: Target, mapModel: ModelT.Type, completion: @escaping (MoyaResult<ModelT>)->Void ) -> Cancellable { return provider.request(target) { (result) in switch result { case .success(let resp): completion(resp.mapModel(resp: resp)) case .failure(let moyaErr): print("无网络请求") completion(.failure(moyaErr.errorCode, moyaErr.errorDescription!)) } } } }