1

RestKit コールバック内から呼び出された場合、PhoneGap コールバックが機能しないようです。RestKit 呼び出しを削除することで、PhoneGap コールバック ロジックが正常に機能することを検証しました (さらに、他のすべての PhoneGap プラグイン コールバックが正常に機能します)。以下のコードでは、RestKit 呼び出しの完了時に loader.onDidLoadResponse が実行されますが、PhoneGap / Cordova コールバック行が実行されても、javascript の対応する完了ルーチンは実行されません。まるでコールバックが消えたかのようです。コンテキストや、RestKit や PhoneGap 非同期ロジックの記述方法に何か問題がありますか?

どんな助けでも大歓迎です。

-(void)GetRestJson:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
{
    NSString* callbackID = [arguments pop];
    NSLog(@"%@",callbackID);
    NSString* url = [arguments objectAtIndex:0];
    NSString* sublocation = [arguments objectAtIndex:1];
    NSDictionary * args = [NSDictionary dictionaryWithObjectsAndKeys:
                           callbackID, @"callBackID",
                           self, @"thisObject",                           
                           nil];
    RKClient* client = [RKClient clientWithBaseURL:[RKURL URLWithString:url]];

// <---- RESTKIT CALL MADE (WORKS)
    [client get:sublocation usingBlock:^(RKRequest* loader)
     {
         loader.onDidLoadResponse = ^(RKResponse *response)     // <---- RESTKIT COMPLETION CALLED (WORKS)
         {
             NSString* result = [response bodyAsString];
             NSString * callbackID = [args objectForKey:@"callBackID"];
             id callingObject = [args objectForKey:@"thisObject"];

             CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                                                               messageAsString: [result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
             [callingObject writeJavascript: [pluginResult toSuccessCallbackString:callbackID]];  // <---- PHONEGAP CALLBACK MADE (BROKEN --- DOESN'T ARRIVE BACK ON JS CALLBACK)

         };

         loader.onDidFailLoadWithError = ^(NSError *error)
         {
             NSString* result = [error description];
             NSLog(@"Loaded payload: %@", result);
             NSString * callbackID = [args objectForKey:@"callBackID"];
             id callingObject = [args objectForKey:@"thisObject"];
             CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                                                               messageAsString: [result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
             [callingObject writeJavascript: [pluginResult toErrorCallbackString:callbackID]];
         };
     }];
}
4

1 に答える 1

1

2 つのあいまいなバグにより、RestKit の完了関数が実行されませんでした。

問題 #1 - PhoneGap 2.0.0 / Cordova 2.0.0 には非同期コールバック ロジックにバグがあります

PhoneGap コールバック ロジックには、別のコンテキストから無関係な呼び出しのコールバック関数をトリガーできるというバグがあります。Javascript からの呼び出しが行われると、PhoneGap は新しい callbackId を生成し、それを cordova.callbacks 配列に追加して、ネイティブ コードに渡します。しばらくして、ネイティブ コードがリクエストを完了すると、javascript を挿入して callbackSuccess または callbackError 関数を呼び出します。それぞれのコールバック ハンドラーは、cordova.callbacks 配列からコールバック属性を検索し、元の呼び出し元の完了関数を実行します。問題は、ネイティブ コードがまだ前の要求を完了していない場合でも、各ページまたはページのリロードで callbackId カウンターがゼロにリセットされ、新しい呼び出しで同じ callbackId が再利用されることです。これは、新しいページのロード時またはアンカー タグ内の空の href のリロード時に発生する可能性があります。

解決策:増加する callbackId を一意の識別子に置き換えて、呼び出し元の完了ロジックのみが呼び出されるようにします。疑似 GUID ジェネレーターでこれを行いました。以下に概説する修正:

cordova.2.0.0.js と cordova.ios.js の両方でこの行を置き換えます

callbackId = service + cordova.callbackId++;    // BUG: incrementing callbackId's can call unrelated callback logic

この行で

callbackId = service + ":" + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {var r = Math.random()*16|0,v=c=='x'?r:r&0x3|0x8;return v.toString(16);}); // Generate unique callbackID with Pseudo-GUID

問題 #2 - 空の href を持つアンカーによるページのリロード

呼び出しページは空の href="" を持つアンカー タグを使用します。これにより、現在のページがリロードされ、$(document).ready が再び起動されます。リロードは、cordova.callbackId カウンターと cordova.callbacks 配列をリセットします。新しく起動された .ready 関数は、ネイティブ コードへの新しい呼び出しを行い、ネイティブ コード内の前のページ インスタンスから既に使用され、保留中の同じ callbackId を再利用します。RestKit 呼び出しが完了すると、PhoneGap/Cordova は、無関係なロジックへの重複したエントリに対して callbackId を起動します。

解決策:上記のように callbackId ロジックを修正すると、関連のないコールバック ロジックが実行されなくなります。解決策の 2 番目の部分は、アンカー タグから href を削除するか、単に div 要素で onclick を使用して、ページのリロードや、callbackId を再利用する新しいページへの移動を防ぐことです。

于 2012-08-31T00:28:57.143 に答える