照着文档和Demo挺顺利就调通了的。记录下制作和调用过程。
阅读提示:
1.本文章仅为iOS原生插件制作,无Android部分。
2.面向有iOS开发基础的读者。
3.我就是参照官方文档做的,如果按照官方文档能直接做好就不用继续看了。
4.操作顺序和官方文档有几处不同,但不会影响最终结果。
uni-app官方文档:uni-app原生插件(native plugin)开发指南
uni-app iOS端官方文档:iOS uni-app原生插件开发文档
(官方Demo在文档中有写,本文是以官方Demo中的uni-app工程为基础的)
共5步,每一步都有很详细的图文讲解。
第一步:准备工作。
第二步:创建iOS原生静态库工程
第三步:把静态库工程添加到uni-app项目中并进行相关配置
第四步:开发桥接类
第五步:使用HBuilder新建uni-app项目调用插件。
第一步:准备。
按照官方文档提示,下载好最新版本的SDK包(里面会有uni-app的工程Demo)以及HBuilderX开发工具。这两个就够。
第二步:创建iOS原生静态库。.a或.framework都可以。官方文档中也给了两个参考链接,我直接搬过来。
这里由于我有界面以及资源文件,所以我习惯选择.framework。还是讲下具体步骤……(我也是根据文章里的步骤一步一步做的,会做的可以跳过不看)
2.1 创建命名为WeexVinOCR的工程后,删掉工程同名.h文件(创建项目自带的),删除后目录如下图所示。
2.2 添加所需文件,把插件实现功能所需的原生类全部拖入。(资源文件不拖,是集成到uni-app后放在uni-app项目里的)拖入时请选择以下三个选项。
2.3 创建一个桥接类继承NSObject,最好命名为XXXModule。(命名规范,取其他的也不会影响,但要记住这个桥接类的名字,后面的步骤要配置的)创建完毕目录如下:(提一句,静态库是可以包含静态库的,我但我只尝试过.framework包含.a和.a包含.a这两种情况)
2.4 接下来是一些framework工程常规设置
(1)TARGETS -> Build Settings -> Build Active Architecture Only 设置为NO,意思是当前打包的.framework支持所有的设备,否则打包时只能用当前版本的模拟器或真机运行。
(2)这里设置最低支持系统
(3)设置编译release包
(4)Command + B编译,看看是否能编译通。我这边报错是因为用到了一些系统库,把他们添加到项目里就行。
添加了相关依赖就好了。
第三步:把.framework工程添加到uni-app工程中,并配置好。
3.1 在Finder中找到.framework工程文件夹和uni-app工程文件夹(我用的是官网下载的Demo)
3.2 打开uni-app项目,把.framework工程添加到项目中。
选择.framework的xcodeproj文件,点击Add
3.3 在Targets -> General -> Frameworks,Libraries,and Embedded Content添加依赖
3.4 可以将插件用到的资源文件拖入项目,请注意是拖入uni-app工程中,而不是.framework工程中(否则我不确定运行的时候能不能正常使用)。资源文件拖入请务必勾选Add to target(否则运行的时候肯定不能正常使用)
3.5 在uni-app项目中注册插件,首先贴上文档的说明
按照文档的说明,我的插件应该是这样配置的。注意,格式以及层次请严格按照图中配置。
(1)hooksClass是类名,这个类是在APP启东市做初始化或者获取系统时间用的,由于我的插件没有用到,所以hooksClass为空。(有这方面需求的需要根据官方文档创建这个类并且进行一系列的相关配置!!我的文章里没有这部分内容,请注意!)
(2)class是.framework中的桥接类的类名(就是之前创建的XXXModule类)
(3)name和class写一样的就行了省事。(但要记住这个字符串,之后js要用到)
3.6 TARGETS -> Build Settings -> Header Search Paths 添加 "$(SRCROOT)/../../SDK/inc" 并设置为recursive。
这个是桥接类开发时用到的头文件的路径,具体因项目而异,官方Demo直接这么配置就行。
第四步:开发桥接类。
4.1 首先在桥接类.h中添加如下图所示代码,然后编译。
这里我第一次开发的时候遇到了报错找不到WXModuleProtocol.h,最后发现竟然是因为我把Demo单独放在了一个地方,编译器就找不到那个头文件了……尽管最后我把那个头文件夹也复制到了对应的地方,也尝试修改相对路径,都行不通。最后还是把Demo放回原处运行才成功的。╮(╯▽╰)╭
如果你也报错找不到头文件的话,那就再次确定下步骤3.6配置的路径是否能找到对应的头文件吧。
4.2 在4.1编译通过的情况下,修改桥接类.m文件如下图所示。
简而言之:
(1)把需要暴露给JS调用的方法通过WX_EXPORT_METHOD()宏定义声明一下
(2)如果想要在不同的方法中使用同一个对象(比如callback回调),可以写作成员变量。(这是iOS的知识啦)
(3)如果想弹出控制器怎么办呢。我怎么获取当前的控制器?官方文档底部(我直接粘贴在文章里,懒癌患者福音)
// 获取当前显示的 UIViewController
+ (UIViewController *)dc_findCurrentShowingViewController {
//获得当前活动窗口的根视图
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *currentShowingVC = [self findCurrentShowingViewControllerFrom:vc];
return currentShowingVC;
}
+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc {
// 递归方法 Recursive method
UIViewController* currentShowingVC;
if ([vc presentedViewController]) {
// 当前视图是被presented出来的
UIViewController* nextRootVC = [vc presentedViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else if([vc isKindOfClass:[UITabBarController class]]) {
// 根视图为UITabBarController
UIViewController *nextRootVC = [(UITabBarController *)vc selectedViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else if ([vc isKindOfClass:[UINavigationController class]]) {
// 根视图为UINavigationController
UIViewController *nextRootVC = [(UINavigationController *)vc visibleViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else {
// 根视图为非导航类
currentShowingVC = vc;
}
return currentShowingVC;
}
第五步:使用HBuilder新建uni-app项目调用插件。(由于没有uni-app和js开发经验,此处只使用最简单直观的方式)
5.1 打开HBuilder,新建uni-app项目,我命名为Uni-VinUniPlugin
5.2 编写JS代码,在index.vue内写如下代码(图后有文字版可以直接复制)。下图所示代码的意思就是界面上有一个按钮,按钮的点击事件调用原生的接口实现功能,然后原生返回数据给JS。
<template>
<view class="content">
<button type="default" :value="value" @click="clickBtn" >我是按钮</button>
</view>
</template>
<script>
const modal = uni.requireNativePlugin('modal');
const vinModule = uni.requireNativePlugin('VinOCRModule');
export default {
data() {
},
onLoad() {
},
methods: {
clickBtn() {
vinModule.show({
position: 'start',
content: "测试文字没啥用",
}, result => {
const msg = JSON.stringify(result);
console.log(msg);
modal.toast({
message: msg,
duration: 1.5
});
});
},
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
5.3 打包
打包好的代码如下图所示,把它拷贝到到HBuilder-uniPlugin工程的Pandora目录下的apps目录下,注意这个生成的文件夹名(官方叫appid),后面要用到
5.4 control.xml里的appid和生成的文件夹名称要改成一样的
大功告成,运行!界面如下:
原生的回调:
官方提示:调试过程中遇到问题:
(1)如果是原生的问题,直接修改原生代码运行就可以了。
(2)如果是js代码的问题,需要修改.nvue或.vue的代码,然后需要重新导出编译后的代码(编译导出代码有可能会报错,注意控制台的日志信息,千万不要把有问题的资源拿去调试),重新将新生成的文件夹拷贝到HBuilder-uniPlugin工程的Pandora文件夹内对应的目录下(直接替换www文件就行,appid不会变),然后务必删除之前的app,再重新运行工程。
2020.3.18补充: HBuilder点击发布的时候提示我要选择微信开发者工具安装目录。我已经安装了微信开发者工具,但是它还是提示请选择正确的路径。原因是前些天我刚更新最新的开发者工具。我的解决办法是去下载个旧版的微信开发者工具。估计HBuilder新版就没这个问题了。
另提示:我的插件无需在app启动时初始化或者获取系统事件,所以没有进行任何这方面的开发和配置。有这部分需求的读者需要自行去官网查漏补缺。(先进行OC和JS的互调,再进行这部分的补充是没啥影响的)