iOSプラグイン開発ガイド
このセクションでは、iOSプラットフォームでネイティブプラグインコードを実装する方法の詳細について説明します。
これを読む前に、プラグインの構造とその共通のJavaScriptインターフェースの概要については、プラグイン開発ガイドを参照してください。このセクションでは、Cordovaウェブビューとネイティブプラットフォーム間で通信するサンプルのechoプラグインをさらに説明します。
iOSプラグインは、CDVPlugin
クラスを拡張するObjective-Cクラスとして実装されます。JavaScriptのexec
メソッドのservice
パラメーターをObjective-Cクラスにマップするには、各プラグインクラスを名前付きアプリケーションディレクトリのconfig.xml
ファイルで<feature>
タグとして登録する必要があります。
プラグインクラスのマッピング
プラグインのJavaScript部分は、次のようにcordova.exec
メソッドを使用します。
exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);
これは、UIWebView
からiOSネイティブ側へのリクエストをマーシャリングし、args
配列に渡された引数を使用して、service
クラスのaction
メソッドを効果的に呼び出します。
プラグイン開発ガイドで説明されているように、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
のライフタイムに対して、プラグインオブジェクトのインスタンスが1つ作成されます。config.xml
でonload
のname
属性が"true"
に設定されている場合を除き、プラグインはJavaScriptからの呼び出しによって初めて参照されるまでインスタンス化されません。例:
<feature name="Echo">
<param name="ios-package" value="Echo" />
<param name="onload" value="true" />
</feature>
プラグインは、起動ロジックにpluginInitialize
メソッドを使用する必要があります。
メディア再生、リスナー、内部状態を維持するなど、長時間実行されるリクエストやバックグラウンドアクティビティを持つプラグインは、それらの長時間実行されるリクエストをキャンセルしたり、それらのアクティビティの後片付けを行うために、onReset
メソッドを実装する必要があります。このメソッドは、JavaScriptを再読み込みするUIWebView
が新しいページに移動したり、更新したりするときに実行されます。
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メッセージタイプ
このパターンに従うクラスメソッドを使用して、さまざまな結果タイプをJavaScriptコールバックに戻すためにCDVPluginResult
を使用できます。
+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...
String
、Int
、Double
、Bool
、Array
、Dictionary
、ArrayBuffer
、およびMultipart
タイプを作成できます。ステータスを送信したり、エラーを返したり、プラグインの結果を送信しないように選択することもできます。その場合、どちらのコールバックも実行されません。
複雑な戻り値については、次の点に注意してください。
-
messageAsArrayBuffer
はNSData*
を期待し、JavaScriptコールバックでArrayBuffer
に変換します。同様に、JavaScriptがプラグインに送信するArrayBuffer
はNSData*
に変換されます。 -
messageAsMultipart
は、他のサポートされているタイプのいずれかを含むNSArray*
を期待し、配列全体をJavaScriptコールバックへのarguments
として送信します。このようにして、すべての引数は必要に応じてシリアル化またはデシリアル化されるため、Array
/Dictionary
としてではなく、NSData*
をマルチパートとして返すことができます。
Echo iOSプラグインの例
アプリケーションプラグインで説明されているJavaScriptインターフェースのecho機能と一致させるには、plugin.xml
を使用して、ローカルプラットフォームのconfig.xml
ファイルにfeature
仕様を挿入します。
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="Echo">
<param name="ios-package" value="Echo" />
</feature>
</config-file>
</platform>
次に、Cordova-iOSアプリケーションディレクトリのPlugins
フォルダに次のEcho.h
ファイルとEcho.m
ファイルを追加します。
/********* 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
配列の最初のパラメーターを取得することで、エコー文字列を取得します。これは、JavaScriptのexec()
関数によって渡された引数に対応します。
パラメーターがnil
または空文字列ではないことを確認し、その場合、ERROR
ステータスを持つPluginResult
を返します。パラメーターがチェックを通過した場合、元のecho
文字列を渡して、OK
ステータスのPluginResult
を返します。最後に、結果をself.commandDelegate
に送信します。これにより、JavaScript側のexec
メソッドの成功または失敗のコールバックが実行されます。成功コールバックが呼び出されると、echo
パラメーターが渡されます。
iOS統合
CDVPlugin
クラスには、プラグインでオーバーライドできる他のメソッドがあります。たとえば、pause、resume、アプリの終了、およびhandleOpenURL
イベントをキャプチャできます。CDVPlugin.hとCDVPlugin.mクラスを参照してください。
WKURLSchemeTaskフック
WKURLSchemeTaskは、CordovaのメインWKWebViewがアプリバンドルからファイルを読み込むために使用するインターフェースです。プラグインで- (BOOL) overrideSchemeTask: (id <WKURLSchemeTask>)urlSchemeTask
メソッドを実装することで、独自の カスタムスキームまたはウェブビューのカスタム読み込みコードを作成できます。
スレッド
プラグインメソッドは通常、メインインターフェースと同じスレッドで実行されます。プラグインに大量の処理が必要な場合、またはブロッキングコールが必要な場合は、バックグラウンドスレッドを使用する必要があります。例:
- (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コンソールにエラーが記録されます。