iOS(Swift) 基于 Moya 的二次封装
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS(Swift) 基于 Moya 的二次封装相关的知识,希望对你有一定的参考价值。
参考技术A Moya+Alamofire是现阶段大部分 Swift 项目所喜欢使用的网络层框架,其简洁明了的协议式接口设计,非常让人上头. 但是项目中,一般都会基于这个框架再进行二次封装,以适用于公司业务.本篇文章就是讲解下我司所封装的框架(大部分一致,但有部分是自己的修改)先说说网络层封装的最终目的,我们希望我们封装的请求框架,调用简单方便,封装简洁清晰易读,易拖展,本身已经具备了基础的加密,debug 打印,业务错误码处理等等功能. 以此为目的,一步步分析下如何封装.
最基础接入:
这种调用弊端很大,我们一般会去做二次的封装,这里讲解下我司封装的网络层框架(我单独把公司框架网络层提取出来,自己做了一点修改).
流程走,先封装 TargetType
这里对 targetType 进行拖展.我们不希望对外暴露 Moya 接口,所有关于 moya 的结构,都进行了二次封装.
APIRoute 是对 method 的二次封装,顺便把 path 也封装进去
Env 是环境配置,属于公司业务范畴,这里不作展示.
我司使用的响应式框架为 ReactiveSwift
Moya 对此的拖展函数为
在此基础上,我们进行封装
我做了一些业务筛减,保留存储的请求处理,说明都在code 里,这里有几个参数定义
在 plugins 基础上,我们定义了一个新的概念,APIPlugin,并且生命周期由rac 控制,其实对 PluginType 做拖展也能做到(选择自己喜欢的即可)
Moya 初始化函数为:
moya 接收一个 [PluginType] 的插件数组初始化,并提供了基础的 log 插件 NetworkLoggerPlugin
PluginType 生命周期函数为
核心调用顺序位置为, moya 实现了alamofire 的RequestInterceptor
数据加密请求,请求头的通用参数,我们可以通过插件形式实现
自定一个插件,实现
用插件实现,结构会非常的清晰
自定义一个 log 插件
注意一点,Moya 框架自带了一个 NetworkLoggerPlugin ,如果不想自定义的话,可以使用它,但是注意它接受一个 Configuration参数
这个参数里面有个Formatter,记得将 data->string, 使用.prettyPrinted,这样打印出来的结果会好看点,我司使用的是自定义,为了区分打印 globalParam, 业务param等等,不过实现原理和 Moya 自带的差不多
从此插件开始,后续均为 APIPlugin
核心是,在 APIProvider 中,我们在执行插件 didEnd之前
APIResponseValidation去 validate APIResult 的业务,如果业务上有特殊需要,可以对特殊的 code,进行错误抛出,比如业务上code: 8888,尽管状态码200,但是我们仍然认为是不成功的一次请求,走的是failed,从而走插件 的 didEnd业务处理(Toast 啥的),而不会进入 success
toast 我简单处理了下,根据自己的业务处理弹窗即可
提到 toast,这里再埋一个坑,toast 大家很常用,但是 toast 封装也很重要,如果有时间,我会抽出我司封装的 toast 组件,非常非常 nice!
稍微透露下
基于ant design form的二次封装
// standardForm.js import React, PureComponent from ‘react‘; import PropTypes from ‘prop-types‘; import Form, Input, Row, Col, Button from ‘antd‘; const FormItem = Form.Item; // 默认的layout export const defaultLabelColSpan = 8; const defaultFormItemLayout = labelCol: span: defaultLabelColSpan , wrapperCol: span: 16 , ; const responsive = 1: xs: 24 , 2: xs: 24, sm: 12 , 3: xs: 24, sm: 12, md: 8 , 4: xs: 24, sm: 12, md: 6 , ; // 监听表单变化 const handleFormChange = (props, changedValues, allValues) => if (props.onChange) props.onChange(allValues); ; class StandardForm extends PureComponent // 渲染单个表单项 renderFormItem = ( item, layout, form, columns ) => const label, key, required, component, options = , rules, extra = item; const col = columns > 4 ? 4 : columns; return ( <Col ...responsive[col] key=key> <FormItem key=key label=label ...layout extra=extra> form.getFieldDecorator(key, normalize: val => (typeof val === ‘string‘ ? val.trim() : val), ...options, form, // 处理复杂的表单校验 rules: rules || [ required, message: `$label不能为空` ], )(component || <Input />) </FormItem> </Col> ); ; onSubmit = e => e.preventDefault(); const onSubmit = this.props; if (onSubmit) onSubmit(); ; render() // items格式即为上文配置的表单项 const onSubmit, items, layout, columns, form = this.props; return ( <Form onSubmit=onSubmit && this.onSubmit> <Row gutter= md: 8, lg: 24, xl: 48 type="flex" align="top"> items.map(item => this.renderFormItem( item, layout, form, columns )) </Row> <Button type="primary" htmlType="submit" style= display: ‘none‘ > 搜索 </Button> </Form> ); // colums [1,2,3,4] StandardForm.propTypes = items: PropTypes.array.isRequired, layout: PropTypes.object, columns: PropTypes.number, form: PropTypes.object.isRequired, ; StandardForm.defaultProps = layout: defaultFormItemLayout, columns: 1, ; export default Form.create( onValuesChange: handleFormChange )(StandardForm);
<StandardForm ref=formRef => this.formRef = formRef; items=formConfig layout= labelCol: span: 7 , wrapperCol: span: 17 , columns=3 />
以上是关于iOS(Swift) 基于 Moya 的二次封装的主要内容,如果未能解决你的问题,请参考以下文章