如果从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]];
};
}];
}
答案 0 :(得分:1)
两个模糊的错误导致RestKit完成函数无法执行:
问题#1 - PhoneGap 2.0.0 / Cordova 2.0.0在异步回调逻辑中存在错误
PhoneGap回调逻辑有一个错误,它可以触发来自不同上下文的无关调用的回调函数。当来自Javascript的调用时,PhoneGap会生成一个新的callbackId,将其添加到cordova.callbacks数组中,并将其传递给本机代码。一段时间后,当本机代码完成请求时,它会注入javascript来调用callbackSuccess或callbackError函数。相应的回调处理程序从cordova.callbacks数组中查找回调属性并执行原始调用者的完成函数。问题是每个页面或页面的重新加载,将callbackId计数器重置为零,并且新调用最终重用相同的callbackId,即使本机代码尚未完成先前的请求。这可以在新页面加载时发生,或者在锚标记中的空href上重新加载。从page1.html调用本机代码可能会触发page2.html上的完成例程,因为本机代码在桥的另一端没有更改的上下文。
解决方案:使用唯一标识符替换递增的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,这些callbackId已经在使用,并且仍然从本机代码中的先前页面实例中挂起。当RestKit调用完成时,PhoneGap / Cordova会将callbackId触发到现在重复的无关逻辑条目。
解决方案:如上所述修复callbackId逻辑可防止不相关的回调逻辑执行。解决方案的第二部分是从锚标记中删除href,或者只是在div元素中使用onclick来防止页面重新加载或导航到重新使用callbackIds的新页面。