照著文檔和Demo挺順利就調(diào)通了的。記錄下制作和調(diào)用過程。
閱讀提示:
1.本文章僅為iOS原生插件制作,無Android部分。
2.面向有iOS開發(fā)基礎的讀者。
3.我就是參照官方文檔做的,如果按照官方文檔能直接做好就不用繼續(xù)看了。
4.操作順序和官方文檔有幾處不同,但不會影響最終結果。
uni-app官方文檔:uni-app原生插件(native plugin)開發(fā)指南
uni-app iOS端官方文檔:iOS uni-app原生插件開發(fā)文檔?
(官方Demo在文檔中有寫,本文是以官方Demo中的uni-app工程為基礎的)
共5步,每一步都有很詳細的圖文講解。
第一步:準備工作。
第二步:創(chuàng)建iOS原生靜態(tài)庫工程
第三步:把靜態(tài)庫工程添加到uni-app項目中并進行相關配置
第四步:開發(fā)橋接類
第五步:使用HBuilder新建uni-app項目調(diào)用插件。
第一步:準備。

按照官方文檔提示,下載好最新版本的SDK包(里面會有uni-app的工程Demo)以及HBuilderX開發(fā)工具。這兩個就夠。
第二步:創(chuàng)建iOS原生靜態(tài)庫。.a或.framework都可以。官方文檔中也給了兩個參考鏈接,我直接搬過來。
這里由于我有界面以及資源文件,所以我習慣選擇.framework。還是講下具體步驟……(我也是根據(jù)文章里的步驟一步一步做的,會做的可以跳過不看)
2.1 創(chuàng)建命名為WeexVinOCR的工程后,刪掉工程同名.h文件(創(chuàng)建項目自帶的),刪除后目錄如下圖所示。

2.2 添加所需文件,把插件實現(xiàn)功能所需的原生類全部拖入。(資源文件不拖,是集成到uni-app后放在uni-app項目里的)拖入時請選擇以下三個選項。

2.3 創(chuàng)建一個橋接類繼承NSObject,最好命名為XXXModule。(命名規(guī)范,取其他的也不會影響,但要記住這個橋接類的名字,后面的步驟要配置的)創(chuàng)建完畢目錄如下:(提一句,靜態(tài)庫是可以包含靜態(tài)庫的,我但我只嘗試過.framework包含.a和.a包含.a這兩種情況)

2.4 接下來是一些framework工程常規(guī)設置
(1)TARGETS -> Build Settings ->?Build Active Architecture Only 設置為NO,意思是當前打包的.framework支持所有的設備,否則打包時只能用當前版本的模擬器或真機運行。

(2)這里設置最低支持系統(tǒng)

(3)設置編譯release包


(4)Command + B編譯,看看是否能編譯通。我這邊報錯是因為用到了一些系統(tǒng)庫,把他們添加到項目里就行。

添加了相關依賴就好了。

第三步:把.framework工程添加到uni-app工程中,并配置好。
3.1 在Finder中找到.framework工程文件夾和uni-app工程文件夾(我用的是官網(wǎng)下載的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啟東市做初始化或者獲取系統(tǒng)時間用的,由于我的插件沒有用到,所以hooksClass為空。(有這方面需求的需要根據(jù)官方文檔創(chuàng)建這個類并且進行一系列的相關配置!!我的文章里沒有這部分內(nèi)容,請注意!)
(2)class是.framework中的橋接類的類名(就是之前創(chuàng)建的XXXModule類)
(3)name和class寫一樣的就行了省事。(但要記住這個字符串,之后js要用到)
3.6?TARGETS -> Build Settings -> Header Search Paths 添加?"$(SRCROOT)/../../SDK/inc" 并設置為recursive。
這個是橋接類開發(fā)時用到的頭文件的路徑,具體因項目而異,官方Demo直接這么配置就行。


第四步:開發(fā)橋接類。
4.1 首先在橋接類.h中添加如下圖所示代碼,然后編譯。

這里我第一次開發(fā)的時候遇到了報錯找不到WXModuleProtocol.h,最后發(fā)現(xiàn)竟然是因為我把Demo單獨放在了一個地方,編譯器就找不到那個頭文件了……盡管最后我把那個頭文件夾也復制到了對應的地方,也嘗試修改相對路徑,都行不通。最后還是把Demo放回原處運行才成功的。╮(╯▽╰)╭
如果你也報錯找不到頭文件的話,那就再次確定下步驟3.6配置的路徑是否能找到對應的頭文件吧。
4.2 在4.1編譯通過的情況下,修改橋接類.m文件如下圖所示。

簡而言之:
(1)把需要暴露給JS調(diào)用的方法通過WX_EXPORT_METHOD()宏定義聲明一下
(2)如果想要在不同的方法中使用同一個對象(比如callback回調(diào)),可以寫作成員變量。(這是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項目調(diào)用插件。(由于沒有uni-app和js開發(fā)經(jīng)驗,此處只使用最簡單直觀的方式)
5.1 打開HBuilder,新建uni-app項目,我命名為Uni-VinUniPlugin

5.2 編寫JS代碼,在index.vue內(nèi)寫如下代碼(圖后有文字版可以直接復制)。下圖所示代碼的意思就是界面上有一個按鈕,按鈕的點擊事件調(diào)用原生的接口實現(xiàn)功能,然后原生返回數(shù)據(jù)給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和生成的文件夾名稱要改成一樣的

大功告成,運行!界面如下:

原生的回調(diào):

官方提示:調(diào)試過程中遇到問題:
(1)如果是原生的問題,直接修改原生代碼運行就可以了。
(2)如果是js代碼的問題,需要修改.nvue或.vue的代碼,然后需要重新導出編譯后的代碼(編譯導出代碼有可能會報錯,注意控制臺的日志信息,千萬不要把有問題的資源拿去調(diào)試),重新將新生成的文件夾拷貝到HBuilder-uniPlugin工程的Pandora文件夾內(nèi)對應的目錄下(直接替換www文件就行,appid不會變),然后務必刪除之前的app,再重新運行工程。
2020.3.18補充: HBuilder點擊發(fā)布的時候提示我要選擇微信開發(fā)者工具安裝目錄。我已經(jīng)安裝了微信開發(fā)者工具,但是它還是提示請選擇正確的路徑。原因是前些天我剛更新最新的開發(fā)者工具。我的解決辦法是去下載個舊版的微信開發(fā)者工具。估計HBuilder新版就沒這個問題了。
另提示:我的插件無需在app啟動時初始化或者獲取系統(tǒng)事件,所以沒有進行任何這方面的開發(fā)和配置。有這部分需求的讀者需要自行去官網(wǎng)查漏補缺。(先進行OC和JS的互調(diào),再進行這部分的補充是沒啥影響的)