前言
一、项目架构
项目按照代码的组织结构和调用关系,可以分为四层,分别是视图层、业务层、基础模块和数据访问层。其中视图层负责页面展示和与用户交互(如用户的点击事件、划动手势等),业务层则对应具体的业务,例如充值模块、用户信息、乘车码、多扣票款等,基础模块包含了项目运行各个功能最基本的能力和组件,比如网络模块负责业务的网络请求,安全模块负责报文的加解密和签名验签,存储模块负责本地的数据持久化等等,数据访问层是对项目所用到的所有信息的获取方式的抽象和封装,包括从接口获取数据,从本地资源文件、本地缓存以及数据库等获取数据。
下面分别对各个模块做下介绍:
1、视图层
2、业务层
3、基础模块
4、数据访问层
二、项目目录结构
1、工程目录结构
工程目录结构如下:
项目采用了cocoapods的集成方式,目录结构主要分为Base、Common、Macro、Main、Resources、Sources、Supporting Files、Vendors、Pods。
其中,
- Base目录下是项目用到的基础ViewController的封装,包含加载WebView的,加载原生页面的,已经他们的共同基类。
- Common目录包含了项目用到的公共代码。
- Macro是对项目常用的宏的汇总。
- Main是项目的主代码目录。
- Resources是项目的资源文件,包含图片、预置离线包等。
- Sources是程序启动相关的源文件。
- Supporting Files包含了main.m也就是程序的入口文件,还有info.plist程序的配置文件,还有启动图等等。
- Vendors是手动导入的第三方库。
- Pods目录下是通过pod导入的第三方库。
2、mPaas目录结构
mPaaS目录结构如下:
└── MPaaS
├── mpaas_sdk.config
├── Targets
| └── mPaaSDemo(工程 Target 名称)
| ├── mPaaSDemo-mPaaS-Headers.h
| ├── mPaaSDemo-Prefix.pch
| ├── APMobileFramework
| ├── mPaas
| ├── meta.config
| └── yw_1222.jpg
├── Resources
└── Frameworks
其中,
mpaas_sdk.config
:当前工程添加的模块信息,包括版本、添加时间、资源文件等,由 mPaaS 插件自动维护,不得手动修改。mPaaSDemo-mPaaS-Headers.h
:当前工程依赖的 mPaaS 模块的头文件,由 mPaaS 插件自动维护,不得手动修改。mPaaSDemo-Prefix.pch
:当前工程 pch 文件的引用,会自动将mPaaSdemo-mPaaS-Headers.h
加入 mPaaS 模块的头文件。APMobileFramework
:mpaas 框架的生命周期管理的 category 文件。mPaas
:MPaaSInterface 的 category 文件。meta.config
:从 mPaaS 控制台下载的云端元数据。yw_1222.jpg
:通过元数据中的 base64code 字段生成的无线保镖验签图片,在移动网关验签时使用。如不需要移动网关功能,可删除此图片。Resources & Frameworks
:mPaaS 模块的资源文件和二进制文件目录,是当前工程所有 Targets 使用的 mPaaS 模块的并集,由 mPaaS 插件自动维护,不得手动修改。
三、开发流程规范
1、需求评审
产品在明确需求之后,通过邮件发出需求文档,然后召集大家一起进行需求评审。参与需求评审的人一般包含负责该项目的产品经理,已及相关测试人员,负责开发的前后端开发人员,部分重要项目领导也会参与评审。
产品经理讲完产品需求后,大家根据需求设计展开讨论,最终大家达成统一意见后,产品发出会议纪要和需求方案的最终版本,客户端开始根据需求文档和UI设计启动流程设计。
2、流程设计
按照产品的需求文档和UI设计,开始绘制流程图。流程图应包含业务的所有流程节点和各种异常情况,重要的网络请求和相关参数。设计文档应该包含业务每一步的操作流程描述,对应的流程图和UI截图,必要业务应有相关时序图。
3、设计评审
完成流程设计之后,像需求评审一样,召集相关人员进行设计评审。开发人员根据设计文档和流程图讲述设计思路,然后征求各方意见,最终大家达成一致后修改设计文档,开始排期。
排期一般包含开发时间,联调时间以及自测时间。可以按照功能或者页面进行排期,排期的单位是人/日。排期完成后发给上级领导审核,审核通过后启动开发。如果排期有问题,则按照领导给出的意见进行调整,直至没有问题后开始开发。
4、开发联调
根据设计流程进行编码,每天的进度会上汇报自己的完成情况,期间定时提交代码和写禅道日志。如果中途发生需求变更或者其他情况(例如后台不具备联调条件),及时向领导说明情况,要求相关人员予以邮件说明,领导同意后酌情调整排期。
开发完毕后启动联调,联调包括与后台联调已经与H5的联调,或者分别称为外部联调和内部联调。如果接口出现任何问题及时和相关开发同事沟通,如果未能达成统一意见,找产品或者相关领导进行讨论协商。
联调完成后进入自测阶段。
5、自测提测
自测阶段根据流程图或者参考测试发出的测试用例,对业务的正常流程和异常情况进行测试,如果发现问题及时修改,保证测试可以顺利进行。
自测通过后发提测邮件,邮件里写明提测的具体功能和对应的开发人员。发送给测试人员,抄送相关开发人员和领导。并在相关群里通知测试人员启动测试。
6、bug修改
提测后每天关注禅道,及时解决测试提出的bug。如果遇到难以复现的bug,找测试沟通,了解相关的复现步骤。如果出现理解不一致的情况找产品进行确认。
待二轮测试通过后,测试发出测试报告,开始合并代码到dev分支,切换本地配置和预置离线包,准备打包加固,启动生产测试。
7、加固打包
使用梆梆的加固客户端SCShieldClient,选择我们的项目目录。配置加固选项后开始加固。加固完成后,打开加固生成的项目目录,开始打包,打包成功后商城APP Store,使用testflight进行生产测试。具体打包流程参见 环境配置。
8、生产提测
加固打包并上传到APP Store后,发生产环境提测邮件,待后台上线完成后,通知测试组进行生产验证。
9、提交审核
测试验证通过后,经产品和领导一致同意,提交审核,是否重置评分选择否,是否分阶段发布选择是,审核通过后选择手动发布。提交审核后,为避免因第三方登录导致审核被拒,通知后台配合修改配置文件,待审核通过后通知后台改回配置。发布的版本号和升级提示内容由产品确定。
如果发生审核被拒,第一时间查明被拒的原因,根据被拒原因找到对应的解决办法,修改后再次提交审核,如果是审核方原因导致的误判等,则通过申诉入口提交申诉。
一般1-2个工作日会有审核结果。如果上线比较紧急,则提交审核的同时补充一份提测邮件。
10、发布上线
审核通过以后,先生成10-20个兑换码进行自测和内部验证。验证通过后,征求领导意见,领导同意后点击发布。是否继续选择分阶段发布根据领导意见来定。
11、线上巡检
上线后第一时间上传符号表到友盟官网,并在git上打tag。定时查看友盟统计的错误日志,发现有错误或者奔溃情况,第一时间分析问题并解决,如果问题比较严重,影响范围比较大,及时汇报领导,征求领导意见是否发布一版紧急修复的版本。
四、第三方库
1、通过Pod引入的第三方库
SDK名称 | 当前版本 | 最新版本 | SDK功能 | 在项目中使用的模块 |
---|---|---|---|---|
JPush | 3.2.8 | 3.7.4 | 极光推送 | 涉及到消息推送相关的 |
JCore | 2.2.5 | 极光核心依赖 | ||
JAnalytics | 2.1.2 | 2.1.2 | 极光统计 | |
JVerification | 2.6.8 | 2.7.5 | 极光运营商的网关认证 | 注册识别本机号码 |
UMengAnalytics | 4.2.5 | 4.2.5 | 友盟统计 | |
PGDatePicker | 2.6.9 | 2.6.9 | 日期选择器 | 选择日期相关模块 |
AFNetworking | 3.2.1 | 4.0.1 | 网络请求 | 所有请求数据相关 |
MJRefresh | 3.1.12 | 3.7.2 | 列表刷新 | 列表,页面刷新相关 |
SVProgressHUD | 2.2.5 | 2.2.5 | hud 提示 | 登录模块网络请求加载 |
MBProgressHUD | 1.2.0 | 1.2.0 | hud 提示 | 公交码,地铁码,以及网络加载结果提示 |
FLAnimatedImage | 1.0.12 | 1.0.16 | gif 动画加载 | 广告相关视频的占位图片展示 |
OpenSDK | 1.8.0 | 微信登录,支付,分享相关 | 登录 充值,分享 | |
JJImagePicker | / | / | 选择照片 | 上传照片相关 |
MSWeakTimer | / | / | 定时器 | 乘车二维码定时更换 |
JDSDK | / | / | 京东相关 | |
LBXScanNative | / | / | 扫码功能,生成二维码 | 公交码、地铁码生成二维码 |
SM2 | / | / | 加密解密 | |
WhiteBox | / | / | 白盒测试 | |
QYSDK | / | / | 网易七鱼客服 | 在线客服 |
OpenSSL | / | / | 创建申请证书加密 | |
UniPaymentcontrol | / | / | 银联支付 | |
JDpay | / | / | 京东支付 | |
YYModel | / | / | 数据转模型 | 数据请求 |
metroSDK | / | / | 地铁乘车码相关 | 地铁码相关 |
iOSPGLib | / | / | 密码安全控件 | 安全键盘 |
WMZBanner | / | / | 轮播图 | 首页广告轮播 |
SJActionSheet | / | / | 弹窗 | |
mPaaS | / | / | 移动开发、测试、运营及运维提供云到端的一站式解决方案 |
2、手动导入的第三方库
五、原生方法
1、离线包调用原生方法
方法名 | 功能 |
---|---|
pushWindow | push页面 |
appSendDataWarpToWeb | 注册离线包通信 |
cardCompareVersion | 区分卡与手机系统 |
toWXLaunchMiniProgram | 跳转微信小程序 |
obtainConfigureInfo | 获取支付顺序 |
setupCurrentUserId | 设置当前UserId |
updateAllNebulaApps | 更新全部离线包 |
updateNebulaApp | 根据AppId更新指定离线包 |
MPNebulaStartApp | 跳转离线包页面appId |
skipOfflineToUrl | 跳转离线包页面url |
obtainCardState | 获取卡状态 |
getCardArray | 获取卡片 |
encryptDataWithRSA3 | 3.0加密 |
decryptDataWithRSA3 | 3.0解密 |
getDeviceParam | 获取当前设备信息 |
electronicMetroAndPayCode | 点击地铁码 |
getUserInfoUnEncode | 获取未加密的用户信息 |
activityFinish | 关闭小程序跳转登录页面 |
getWolfcertTokenString | 获取3.0接口token |
showLoadingView | 注册全局加载 |
obtainPublicNoticeMessage | 首页自定义消息,获取保存在本地的消息 |
OpenBankHTMLWebview | 跳转先乘后付绑卡页面 |
toWebViewWithUrlAndTitle | 根据URL跳转webview |
obtainClientBaseUrl | 获取生产或者测试 环境baseURL |
shopClientBaseUrl | 获取商城生产或者测试 环境baseURL |
isPhoneHaveNFC | 获取手机是否设置NFC功能 |
resetScreenLight | 还原手机当前屏幕亮度 |
setScreenLight | 设置手机屏幕亮度为最高 |
getLoginUserInfo | 获取登录用户的信息并保存 |
getBasicInfo | 获取版本基础信息 |
isClickfaceSwitch | 点击指纹解锁 |
tsmEncryptDataWithRSA | 获取加密信息 |
tsmDecryptDataWithRSA | 解密信息 |
AddEventburyPoints | 极光统计 |
getMetroCode | 获取地铁码数据 |
sm4DecryptStringWithBase64 | 注册SM4 |
sm2SignPlainText | 注册SM2 |
imageConvertBase64Code | 注册图片转base64 |
callThirdPayment | 跳转支付 |
skipPaymentSign | 跳转签约 |
skipWechatLogin | 跳转微信登录 |
wechatAuthorize | 微信授权认证 |
skipAlipayAuthorization | 支付宝授权认证 |
toWebViewWithUrlAndTitleRevised | 跳转webview |
checkiOSVersionUpdate | 版本更新检测 |
openQRCode | 跳转公交码和地铁码 |
receiveFacedIdentifyCode | 获取人脸识别登录code方法 |
YKTFacedIdentifyPhoto | 人脸识别头像上传 |
skipFacedIdentify | 跳转人脸识别getFaceCode |
shareWechatUrl | 微信分享 |
openElectronicInvoice | 跳转电子发票 |
advertisingMoreState | 用户是否关闭过广告位 |
advertisingMoreClose | 用户关闭广告位 |
toOnLineServiceUrlAndTitle | 跳转客服 |
jPushLoginStatus | 一键登录返回结果 |
jumpPageToLogin | 一键登录 |
upQrPayNotice | 获取是否设置默认支付渠道 |
isSatisfyNFC | 是否满足NFC使用条件 |
setPayMentContract | 是否支付渠道解约 |
freePayMentContract | 移除本地支付渠道解约 |
isHiddenWechat | 微信登录是否展示 |
YKTClosePage | 关闭页面 |
defaultToQR | 设置公交/地铁 |
getDefaultToQR | 获取是否设置公交/地铁 |
YKTShowPassKeyboard | 展示密码键盘 |
isSupportNFCCard | 判断手机是否有NFC |
invalidateNFCScan | NFC扫描终止 |
startNFCScan | NFC开始扫描 |
endNFCScan | NFC扫描结束 |
nfcExecuteApdu | NFC扫描执行APDU |
updateTip | NFC扫描更新提示 |
nfcCardTouch | NFC贴卡开始 |
getNfcCardParams | 获取NFC扫描参数 |
getLocationPermission | 获取手机定位权限 |
YKTJSPostMessage | 发送通知 |
loginSuccess | 登录成功刷新首页消息 |
logoutSuccess | 退出成功清除首页自定义消息 |
skipUnipayAuthorization | 云闪付签约 |
YKTSafeControlShow | 安全键盘显示 |
YKTSafeControlClearPassword | 安全键盘清空 |
YKTSafeControlHidePassword | 安全键盘隐藏 |
YKTApplePay | Apple pay 调起操作 |
ApplePayCallBack | Apple pay 回调 |
YKTPhotoDelete | 移除手机照片 |
YKTPhotoPicker | 选择照片 |
YKTDateTimePicker | 选择日期 |
YKTSubmitPhoto | 提交选择的照片 |
YKTH5PageRefresh | 页面刷新 |
YKTResetNavBarBackType | 重置导航栏返回按钮样式 |
YKTConfigureNavBarBackType | 配置默认导航栏返回按钮样式 |
YKTHideNavBar | 隐藏导航栏 |
YKTSetupNavBarTranslucent | 导航栏透明 |
YKTSetupStatusBarStyle | 导航栏类型 |
YKTApplyCard | 注册开卡 |
skipAPPLocation | 跳转应用 |
2、普通Html页面调用原生方法
pushWindow | push页面 |
---|---|
appSendDataWarpToWeb | 注册离线包通信 |
cardCompareVersion | 区分卡与手机系统 |
toWXLaunchMiniProgram | 跳转微信小程序 |
obtainConfigureInfo | 获取支付顺序 |
setupCurrentUserId | 设置当前UserId |
updateAllNebulaApps | 更新全部离线包 |
updateNebulaApp | 根据AppId更新指定离线包 |
MPNebulaStartApp | 跳转离线包页面appId |
skipOfflineToUrl | 跳转离线包页面url |
obtainCardState | 获取卡状态 |
getCardArray | 获取卡片 |
encryptDataWithRSA3 | 3.0加密 |
decryptDataWithRSA3 | 3.0解密 |
getDeviceParam | 获取当前设备信息 |
electronicMetroAndPayCode | 点击地铁码 |
getUserInfoUnEncode | 获取未加密的用户信息 |
activityFinish | 关闭小程序跳转登录页面 |
getWolfcertTokenString | 获取3.0接口token |
showLoadingView | 注册全局加载 |
obtainPublicNoticeMessage | 首页自定义消息,获取保存在本地的消息 |
OpenBankHTMLWebview | 跳转先乘后付绑卡页面 |
toWebViewWithUrlAndTitle | 根据URL跳转webview |
obtainClientBaseUrl | 获取生产或者测试 环境baseURL |
shopClientBaseUrl | 获取商城生产或者测试 环境baseURL |
isPhoneHaveNFC | 获取手机是否设置NFC功能 |
resetScreenLight | 还原手机当前屏幕亮度 |
setScreenLight | 设置手机屏幕亮度为最高 |
getLoginUserInfo | 获取登录用户的信息并保存 |
getBasicInfo | 获取版本基础信息 |
isClickfaceSwitch | 点击指纹解锁 |
tsmEncryptDataWithRSA | 获取加密信息 |
tsmDecryptDataWithRSA | 解密信息 |
AddEventburyPoints | 极光统计 |
getMetroCode | 获取地铁码数据 |
sm4DecryptStringWithBase64 | 注册SM4 |
sm2SignPlainText | 注册SM2 |
imageConvertBase64Code | 注册图片转base64 |
callThirdPayment | 跳转支付 |
skipPaymentSign | 跳转签约 |
skipWechatLogin | 跳转微信登录 |
wechatAuthorize | 微信授权认证 |
skipAlipayAuthorization | 支付宝授权认证 |
toWebViewWithUrlAndTitleRevised | 跳转webview |
checkiOSVersionUpdate | 版本更新检测 |
openQRCode | 跳转公交码和地铁码 |
receiveFacedIdentifyCode | 获取人脸识别登录code方法 |
YKTFacedIdentifyPhoto | 人脸识别头像上传 |
skipFacedIdentify | 跳转人脸识别getFaceCode |
shareWechatUrl | 微信分享 |
openElectronicInvoice | 跳转电子发票 |
advertisingMoreState | 用户是否关闭过广告位 |
advertisingMoreClose | 用户关闭广告位 |
toOnLineServiceUrlAndTitle | 跳转客服 |
jPushLoginStatus | 一键登录返回结果 |
jumpPageToLogin | 一键登录 |
upQrPayNotice | 获取是否设置默认支付渠道 |
isSatisfyNFC | 是否满足NFC使用条件 |
setPayMentContract | 是否支付渠道解约 |
freePayMentContract | 移除本地支付渠道解约 |
isHiddenWechat | 微信登录是否展示 |
YKTClosePage | 关闭页面 |
defaultToQR | 设置公交/地铁 |
getDefaultToQR | 获取是否设置公交/地铁 |
YKTShowPassKeyboard | 展示密码键盘 |
isSupportNFCCard | 判断手机是否有NFC |
invalidateNFCScan | NFC扫描终止 |
startNFCScan | NFC开始扫描 |
endNFCScan | NFC扫描结束 |
nfcExecuteApdu | NFC扫描执行APDU |
updateTip | NFC扫描更新提示 |
nfcCardTouch | NFC贴卡开始 |
getNfcCardParams | 获取NFC扫描参数 |
getLocationPermission | 获取手机定位权限 |
YKTJSPostMessage | 发送通知 |
loginSuccess | 登录成功刷新首页消息 |
logoutSuccess | 退出成功清除首页自定义消息 |
skipUnipayAuthorization | 云闪付签约 |
YKTSafeControlShow | 安全键盘显示 |
YKTSafeControlClearPassword | 安全键盘清空 |
YKTSafeControlHidePassword | 安全键盘隐藏 |
YKTApplePay | Apple pay 调起操作 |
ApplePayCallBack | Apple pay 回调 |
YKTPhotoDelete | 移除手机照片 |
YKTPhotoPicker | 选择照片 |
YKTDateTimePicker | 选择日期 |
YKTSubmitPhoto | 提交选择的照片 |
YKTH5PageRefresh | 页面刷新 |
YKTResetNavBarBackType | 重置导航栏返回按钮样式 |
YKTConfigureNavBarBackType | 配置默认导航栏返回按钮样式 |
YKTHideNavBar | 隐藏导航栏 |
YKTSetupNavBarTranslucent | 导航栏透明 |
YKTSetupStatusBarStyle | 导航栏类型 |
YKTApplyCard | 注册开卡 |
skipAPPLocation | 跳转应用 |
getCurrentLocationParam | 获取当前位置经纬度 |
六、mPaas框架
mPaas框架、mPaas、热修复、离线包、小程序
1、mPaas接入
mPaas接入方式共有两种,一种是基于mPaas框架接入,另一种是基于已有工程接入。其中基于已有工厂接入可以使用 mPaaS 插件接入,也可以使用 CocoaPods 接入。我们目前使用的是mPaaS 插件接入方式。具体接入步骤如下:
①安装 mPaaS Xcode Extension;
前置条件:
a、安装了 Xcode。目前 mPaaS Xcode Extension 仅支持 9.0(含)和 12.2(含)之间版本的 Xcode。
b、macOS 版本 ≥ 10.13。
c、未安装过 mPaaS Xcode Extension(如果想升级安装,建议直接使用插件内的升级功能)。
具体步骤:
1、在终端运行以下安装命令。
curl -sSL https://mpaas-ios.oss-cn-hangzhou.aliyuncs.com/mpaaskit/Xcode-extension/install.sh | sh
2、安装完成后,会打开引导页面,点击 开始使用 (或者关闭页面,手动重启 Xcode)即可使用。
3、打开任意 Xcode 工程,在 Xcode 左侧工程结构面板中选择任意可编辑文件(如:main.m),若能看到菜单 Editor > mPaaS,则说明 mPaaS 插件加载成功。
4、导入配置文件后,使用编辑模块为项目添加和删除对应的组件,点击开始编辑后项目启动配置。
②在控制台创建应用;
1、打开mpaas官网的管理平台,点击创建mPaas应用,输入应用名称点击确定,创建应用;
2、点击代码配置,配置对应的Bundle ID;
3、下载配置文件,通过mPaasPlugin配置项目;
注意:配置文件区分测试环境和生产环境。
2、mPaas项目配置
通过mPaas插件配置项目步骤如下:
1、点击 Xcode 菜单项 Editor > mPaaS > 编辑工程,打开编辑工程页面。
2、选择 导入云端元数据 菜单,点击 选择配置文件 按钮,选中第二步中下载的 .config 配置文件,点击 开始导入 按钮,将对应的配置导入到当前工程中。
说明:选择配置文件之后,可以点击 “X” 按钮来关闭,只有点击 开始导入 之后配置才会生效。
3、点击界面上的 编辑模块 菜单,工作区会展示未集成的提示页面。
4、点击 添加模块 会弹出 模块列表 编辑页面。进入页面会提示选择集成的 基线类型和版本,默认为最新基线,点击 确认 按钮。
4、收起基线选择菜单后,下方会刷新出对应基线的模块列表,在列表中点击卡片来添加对应的模块。
5、点击每个模块右侧的 详情 按钮可以查看该模块的具体信息,包括描述、Release Note、包含的 framework 文件详情等。
6、选择好需要添加的模块后,点击右上角的 保存 按钮保存编辑结果,同时返回到主页面,工作区的模块列表中会展示编辑的结果。
7、返回主页面后,点击 开始编辑,将选择的模块添加到当前工程中。
说明:只有点击开始编辑之后,结果才会生效。
8、重新启动当前工程,您会看到工程中新增了与工程文件同级的 mPaaS 目录, mPaaS 相关的文件都在该目录下。
9、直接 build 工程,确保工程可以编译通过。至此您已成功完成 mPaaS 接入过程。
3、离线包配置
1、添加 SDK
项目使用 mPaaS Xcode Extension方式添加
①点击 Xcode 菜单项 Editor > mPaaS > 编辑工程,打开编辑工程页面。
②选择 H5 容器&离线包,保存后点击 开始编辑,即可完成添加。
2、使用 SDK
启动容器
为了使用 Nebula 容器,需要在程序启动完成后调用 SDK 接口,对容器进行初始化。初始化必须在 DTFrameworkInterface
的 - (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中进行。
- (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 初始化容器
[MPNebulaAdapterInterface initNebula];
}
由于我们使用 预置离线包、自定义 JSAPI 和 Plugin 等功能,所以需要使用 initNebula
接口替换为下方代码中的 initNebulaWith
接口,传入对应参数对容器进行初始化。
presetApplistPath
:自定义的预置离线包的包信息路径。
appPackagePath
:自定义的预置离线包的包路径。
pluginsJsapisPath
自定义 JSAPI 和 Plugin 文件的存储路径。
- (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 初始化容器
NSString *presetApplistPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"MPCustomPresetApps.bundle/h5_json.json"] ofType:nil];
NSString *appPackagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"MPCustomPresetApps.bundle"] ofType:nil];
NSString *pluginsJsapisPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Poseidon-UserDefine-Extra-Config.plist"] ofType:nil];
[MPNebulaAdapterInterface initNebulaWithCustomPresetApplistPath:presetApplistPath customPresetAppPackagePath:appPackagePath customPluginsJsapisPath:pluginsJsapisPath];
}
说明:initNebula
和 initNebulaWithCustomPresetApplistPath
是两个并列的方法,不能同时使用。
定制容器
通过设置 MPNebulaAdapterInterface
的属性值来定制容器配置。必须在 DTFrameworkInterface
的 - (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中设置,否则会被容器默认配置覆盖。
- (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 定制容器
[MPNebulaAdapterInterface shareInstance].nebulaVeiwControllerClass = [MPH5WebViewController class];
[MPNebulaAdapterInterface shareInstance].nebulaNeedVerify = NO;
[MPNebulaAdapterInterface shareInstance].nebulaUserAgent = @"mPaaS/Portal";
[MPNebulaAdapterInterface shareInstance].nebulaCommonResourceAppList = @[@"77777777"];
}
更新离线包
启动完成后,全量请求所有离线包信息,检查服务端是否有更新包。为了不影响应用启动速度,建议在 (void)application:(UIApplication \*)application afterDidFinishLaunchingWithOptions:(NSDictionary \*)launchOptions
之后调用。
- (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 定制容器
[MPNebulaAdapterInterface shareInstance].nebulaVeiwControllerClass = [MPH5WebViewController class];
[MPNebulaAdapterInterface shareInstance].nebulaNeedVerify = NO;
[MPNebulaAdapterInterface shareInstance].nebulaUserAgent = @"mPaaS/Portal";
[MPNebulaAdapterInterface shareInstance].nebulaCommonResourceAppList = @[@"77777777"];
// 全量更新离线包
[[MPNebulaAdapterInterface shareInstance] requestAllNebulaApps:^(NSDictionary *data, NSError *error) {
NSLog(@"");
}];
}
4、热修复配置
1、添加 SDK
如下图所示,使用 mPaaS 插件添加 Hotpatch SDK。更多信息,请参考 mPaaS 插件 > 编辑模块 。
2、使用 SDK
添加 SDK 之后,要按照以下描述配置工程:
在 info.plist 中配置应用版本 Product Version。在发布平台中,需要根据这里配置的版本号进行发布。
发布平台支持白名单灰度发布。在这种情况下,客户端去拉取热修复脚本时,服务端会根据白名单判
断是否下发热修复包给该用户。为此,客户端在 MPaaSInterface 的 category 中,需指定用户的 userID。
3、管理加密信息
执行以下命令生成公钥文件(public_key.pem)和私钥文件(private_key.pem),将公钥文件添加到工程中:
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -p
在 main.m 中验证公钥自身的签名,以确保公钥文件未被替换。具体步骤如下:
执行以下命令生成公钥文件的签名二进制串:
mpaas inst hotpatch sign -i /path/to/rsa_public_key.pem -p /path/to/rsa_private_key.pem -o
/path/to/output.sig
-i:openssl 生成的公钥文件 public_key.pem
-p:openssl 生成的私钥文件 private_key.pem
-o:签名二进制串输出文件
将终端打印出来的签名数组拷贝到 main.m 方法中,对公钥自身进行签名。示例代码如下:
说明:若 initDynamicSec() 返回 NO,则说明公私钥不匹配,需要修改,否则平台下发的包在客户端会校验不过,从而导致热修复失败。
5、小程序配置
1、添加 SDK
使用 mPaaS Xcode Extension基于已有工程的接入方式。
2、使用 SDK
1. 初始化配置
初始化容器
容器初始化操作包括启动容器、定制容器和更新小程序包。
1.1启动容器
为了使用 Nebula 容器,需要在程序启动完成后调用 SDK 接口,对容器进行初始化。必须在 DTFrameworkInterface
的 - (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中进行初始化。
- (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 初始化容器
[MPNebulaAdapterInterface initNebula];
}
1.2定制容器
通过设置 MPNebulaAdapterInterface
的属性值来定制容器配置。必须在 DTFrameworkInterface
的 - (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中设置,否则会被容器默认配置覆盖。
- (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 定制容器
[MPNebulaAdapterInterface shareInstance].nebulaVeiwControllerClass = [MPH5WebViewController class];
[MPNebulaAdapterInterface shareInstance].nebulaNeedVerify = NO;
[MPNebulaAdapterInterface shareInstance].nebulaUserAgent = @"mPaaS/Portal";
}
1.3更新小程序
启动完成后,全量请求所有小程序包信息,检查服务端是否有更新包。为了不影响应用启动速度,建议在 (void)application:(UIApplication \*)application afterDidFinishLaunchingWithOptions:(NSDictionary \*)launchOptions
之后调用。
- (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 定制容器
[MPNebulaAdapterInterface shareInstance].nebulaVeiwControllerClass = [MPH5WebViewController class];
[MPNebulaAdapterInterface shareInstance].nebulaNeedVerify = NO;
[MPNebulaAdapterInterface shareInstance].nebulaUserAgent = @"mPaaS/Portal";
[MPNebulaAdapterInterface shareInstance].nebulaCommonResourceAppList = @[@"77777777"];
// 全量更新小程序包
[[MPNebulaAdapterInterface shareInstance] requestAllNebulaApps:^(NSDictionary *data, NSError *error) {
NSLog(@"");
}];
}
初始化完成后,效果如下:
2、配置小程序
2.1 配置权限
在 info.plist
中配置以下 App 权限:
NSBluetoothAlwaysUsageDescription
:蓝牙权限(iOS 13 中的新增权限)。NSCameraUsageDescription
:相机权限。NSPhotoLibraryUsageDescription
:相册权限。NSLocationWhenInUseUsageDescription
:定位权限。
2.2 配置动态库
在当前工程 TARGETS 的 General > Embedded Binaries 中添加 FalconLooks
库。
说明:
- 配置动态库在 10.1.68.15(含)及以上版本基线中已经取消,无需配置。