iOS 插件開發指南
本節提供如何在 iOS 平台上實作原生插件程式碼的詳細資訊。
在閱讀本節之前,請參閱插件開發指南,以了解插件的結構及其常見的 JavaScript 介面。本節將繼續示範範例 echo 插件,該插件會從 Cordova 的 webview 與原生平台之間進行通訊。
iOS 插件會實作成一個繼承自 CDVPlugin
類別的 Objective-C 類別。為了讓 JavaScript 的 exec
方法的 service
參數對應到一個 Objective-C 類別,每個插件類別都必須在指定的應用程式目錄的 config.xml
檔案中註冊為 <feature>
標籤。
插件類別對應
插件的 JavaScript 部分會使用 cordova.exec
方法,如下所示
exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);
這會將請求從 UIWebView
傳送到 iOS 原生端,有效地呼叫 service
類別的 action
方法,並將引數傳遞到 args
陣列中。
使用 plugin.xml
檔案自動注入此標記,在您的 Cordova-iOS 應用程式專案的 config.xml
檔案中,將插件指定為 <feature>
標籤,如插件開發指南中所述
<feature name="LocalStorage">
<param name="ios-package" value="CDVLocalStorage" />
</feature>
功能的 name
屬性應與您指定為 JavaScript exec
呼叫的 service
參數的內容相符。value
屬性應與插件的 Objective-C 類別的名稱相符。<param>
元素的 name
應始終為 ios-package
。如果您未遵循這些準則,插件可能會編譯,但 Cordova 仍然可能無法存取它。
插件初始化與生命週期
在每個 UIWebView
的生命週期中,都會建立一個插件物件的實例。除非在 config.xml
中將具有 onload
name
屬性的 <param>
設定為 "true"
,否則直到 JavaScript 第一次呼叫參考它們時,才會實例化插件。例如,
<feature name="Echo">
<param name="ios-package" value="Echo" />
<param name="onload" value="true" />
</feature>
插件應使用 pluginInitialize
方法進行啟動邏輯。
具有長時間執行請求或背景活動(例如媒體播放、監聽器或維護內部狀態)的插件應實作 onReset
方法,以取消這些長時間執行的請求或在這些活動後進行清理。當 UIWebView
導覽至新頁面或重新整理時,會執行此方法,這會重新載入 JavaScript。
撰寫 iOS Cordova 插件
JavaScript 呼叫會向原生端觸發插件請求,而對應的 iOS Objective-C 插件會在 config.xml
檔案中正確對應,但是最終的 iOS Objective-C 插件類別看起來如何?使用 JavaScript 的 exec
函式派送到插件的任何內容,都會傳遞到對應的插件類別的 action
方法中。插件方法具有此簽章
- (void)myMethod:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult = nil;
NSString* myarg = [command.arguments objectAtIndex:0];
if (myarg != nil) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
如需更多詳細資訊,請參閱CDVInvokedUrlCommand.h、CDVPluginResult.h 和 CDVCommandDelegate.h。
iOS CDVPluginResult 訊息類型
您可以使用 CDVPluginResult
將各種結果類型傳回 JavaScript 回呼,並使用遵循此模式的類別方法
+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...
您可以建立 String
、Int
、Double
、Bool
、Array
、Dictionary
、ArrayBuffer
和 Multipart
類型。您也可以省略任何引數來傳送狀態、傳回錯誤,甚至選擇不傳送任何插件結果,在這種情況下,也不會觸發任何回呼。
請注意以下複雜的傳回值
-
messageAsArrayBuffer
預期NSData*
,並在 JavaScript 回呼中轉換為ArrayBuffer
。同樣地,JavaScript 傳送到插件的任何ArrayBuffer
都會轉換為NSData*
。 -
messageAsMultipart
預期NSArray*
包含任何其他支援的類型,並將整個陣列作為arguments
傳送到您的 JavaScript 回呼。這樣,所有引數都會視需要序列化或還原序列化,因此將NSData*
作為 multipart 傳回是安全的,但不作為Array
/Dictionary
傳回。
Echo iOS 插件範例
若要比對應用程式插件中描述的 JavaScript 介面 echo 功能,請使用 plugin.xml
將 feature
規格注入到本機平台的 config.xml
檔案中
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="Echo">
<param name="ios-package" value="Echo" />
</feature>
</config-file>
</platform>
然後,我們會將下列 Echo.h
和 Echo.m
檔案新增至 Cordova-iOS 應用程式目錄中的 Plugins
資料夾
/********* Echo.h Cordova Plugin Header *******/
#import <Cordova/CDVPlugin.h>
@interface Echo : CDVPlugin
- (void)echo:(CDVInvokedUrlCommand*)command;
@end
/********* Echo.m Cordova Plugin Implementation *******/
#import "Echo.h"
#import <Cordova/CDVPlugin.h>
@implementation Echo
- (void)echo:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult = nil;
NSString* echo = [command.arguments objectAtIndex:0];
if (echo != nil && [echo length] > 0) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@end
檔案頂端的必要匯入會從 CDVPlugin
擴充類別。在本例中,插件僅支援單一 echo
動作。它會藉由呼叫 objectAtIndex
方法,取得 arguments
陣列的第一個參數來取得 echo 字串,這對應於 JavaScript exec()
函式傳遞的引數。
它會檢查參數以確保它不是 nil
或空字串,如果是,則傳回具有 ERROR
狀態的 PluginResult
。如果參數通過檢查,則會傳回具有 OK
狀態的 PluginResult
,並傳入原始的 echo
字串。最後,它會將結果傳送到 self.commandDelegate
,這會在 JavaScript 端執行 exec
方法的成功或失敗回呼。如果呼叫成功回呼,則會傳入 echo
參數。
iOS 整合
CDVPlugin
類別具有您的插件可以覆寫的其他方法。例如,您可以擷取 暫停、繼續、應用程式終止和 handleOpenURL
事件。請參閱 CDVPlugin.h 和 CDVPlugin.m 類別以取得指引。
WKURLSchemeTask 鉤子
WKURLSchemeTask 是 Cordova 的主要 WKWebView 用於從您的應用程式套件載入檔案的介面。您可以藉由在插件中實作 - (BOOL) overrideSchemeTask: (id <WKURLSchemeTask>)urlSchemeTask
方法,為 webview 建立自己的自訂配置或自訂載入程式碼。
執行緒
插件方法通常會在與主介面相同的執行緒中執行。如果您的插件需要大量的處理或需要封鎖呼叫,您應該使用背景執行緒。例如
- (void)myPluginMethod:(CDVInvokedUrlCommand*)command
{
// Check command.arguments here.
[self.commandDelegate runInBackground:^{
NSString* payload = nil;
// Some blocking logic...
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
// The sendPluginResult method is thread-safe.
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}];
}
偵錯 iOS 插件
若要在 Objective-C 端偵錯,您需要 Xcode 的內建偵錯工具。對於 JavaScript,您可以將 Safari 連接到 iOS 模擬器/裝置中執行的應用程式。
常見陷阱
-
別忘了將插件的對應新增至
config.xml
。如果您忘記,則會在 Xcode 主控台中記錄錯誤。 -
別忘了在允許清單中新增您連線的任何主機,如網域允許清單指南中所述。如果您忘記,則會在 Xcode 主控台中記錄錯誤。