Skip to content

Commit

Permalink
Changed JS->Obj-C callback mechanism to use a hidden iframe instead o…
Browse files Browse the repository at this point in the history
…f "location.replace". [Fixes #6]
  • Loading branch information
newyankeecodeshop committed May 16, 2012
1 parent 4e60e3e commit 342377d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 17 deletions.
4 changes: 2 additions & 2 deletions Classes/GAScriptBlockObject.m
Expand Up @@ -65,9 +65,9 @@ - (void)dealloc
- (NSString *)stringForJavaScript
{
NSAssert(m_block, @"Block for callback cannot be NULL!");
GADebugStr(@"ScriptBlockObject: function () { GAJavaScript.invocation('%@', arguments); }", m_blockId);
GADebugStr(@"ScriptBlockObject: GAJavaScript.invocation('%@')", m_blockId);

return [NSString stringWithFormat:@"function () { GAJavaScript.invocation('%@', arguments); }", m_blockId];
return [NSString stringWithFormat:@"GAJavaScript.invocation('%@')", m_blockId];
}

@end
Expand Down
8 changes: 7 additions & 1 deletion Tests/TScriptObject.m
Expand Up @@ -199,7 +199,13 @@ - (void)testCallFunction
GHAssertTrue([retVal isKindOfClass:[NSError class]], nil);
NSError* myErr = (NSError *)retVal;
GHAssertEquals([myErr domain], GAJavaScriptErrorDomain, @"Wrong error domain");
GHAssertEqualStrings([myErr localizedDescription], @"Result of expression 'func' [undefined] is not an object.", @"Wrong error message");

// The error message text changed on iOS 5, so we test for it by checking for the new UIWebView method.
//
if ([_engine.webView respondsToSelector:@selector(mediaPlaybackAllowsAirPlay)])
GHAssertEqualStrings([myErr localizedDescription], @"'undefined' is not an object", @"Wrong error message");
else
GHAssertEqualStrings([myErr localizedDescription], @"Result of expression 'func' [undefined] is not an object.", @"Wrong error message");
}

- (void)testJavaScriptTrue
Expand Down
57 changes: 43 additions & 14 deletions ga-js-runtime.js
Expand Up @@ -26,8 +26,35 @@
or implied, of Andrew Goodale.
*/

GAJavaScript = {
GAJavaScript =
function () {

/**
* Uses an iframe navigation to cause the UIWebViewDelegate to be called.
* The custom URL scheme identifies this request as the "trigger" to make Obj-C calls.
* Note that call happens asynchronously, so a script can queue several calls that will be invoked in order when the run loop is ready.
*/
function callScriptEngine () {
var iframe = document.getElementById("gajavascript_frame");

if (iframe === null) {
iframe = document.createElement("iframe");
iframe.id = "gajavascript_frame";
iframe.style = "display: none";
iframe.src = "ga-js:makeLotsaCalls";

document.documentElement.appendChild(iframe); // will make the callback happen
}
else {
iframe.src = iframe.src; // a kind of "refresh"

// Experimental: The two statements below would cause Obj-C to be invoked synchronously.
// document.documentElement.removeChild(iframe);
// document.documentElement.appendChild(iframe);
}
}

return {
ref: {
index: 0
},
Expand Down Expand Up @@ -146,22 +173,24 @@ GAJavaScript = {
},

performSelector: function (selName) {
var newCall = {
this.calls.push({
sel: selName,
args: Array.prototype.slice.call(arguments) // Converts it to a true Array
};
this.calls.push(newCall);

location.replace("ga-js:makeLotsaCalls");
});

callScriptEngine();
},

invocation: function (invocationHash, callArguments) {
var newCall = {
inv: invocationHash,
args: Array.prototype.slice.call(callArguments) // Converts it to a true Array
};
this.calls.push(newCall);
invocation: function (invocationHash) {

location.replace("ga-js:makeLotsaCalls");
return function () {
GAJavaScript.calls.push({
inv: invocationHash,
args: Array.prototype.slice.call(arguments) // Converts it to a true Array
});

callScriptEngine();
};
}
};
}
}();

0 comments on commit 342377d

Please sign in to comment.