For an extended period on the Mac (since Mac OS 10.3), we’ve enjoyed effective, albeit unconventional, interoperability between Objective-C and JavaScript through the WebScriptObject. Using the WebKit WebView, engaging functionalities like the following was possible:
Even Objective-C could be invoked from JavaScript using bridged objects:objectiveWebView *webView = [[WebView alloc] init]; WebScriptObject *script = [webView windowScriptObject]; id three = [script evaluateWebScript:@"1+2"]; NSAssert([three isEqual:@(3)], @"as expected");
Referring to the API as "weird" is apt, given the necessity to implement NSObject informal protocol methods likeobjectiveWebView *webView = [[WebView alloc] init]; WebScriptObject *script = [webView windowScriptObject]; script[@"myObject"] = [[SomeObject alloc] init]; id selectorResult = [script evaluateWebScript:@"myObject.invokeASelectorAsIfItWereAFunction()"];
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
for JavaScript to invoke arbitrary methods on classes. Despite lacking comprehensive error handling, the overall functionality allowed seamless communication between Objective-C and JavaScript, widely employed in numerous Mac apps.The introduction of Mac OS 10.5 significantly enhanced JavaScript interoperability by exposing a C API to the underlying JavaScript engine (JavaScriptCore) used by WebKit. Although the C API was somewhat cumbersome, Objective-C wrapper libraries, such as JSCocoa, alleviated the challenges.On iOS' UIWebView, JavaScript interoperability had been limited to thestringByEvaluatingJavaScriptFromString
method:However, the lack of interoperability between Objective-C and JavaScript prompted developers to create makeshift bridges, often involving URL-encoded data in conjunction with delegate methods likeobjectiveUIWebView *webView = [[UIWebView alloc] init]; NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"1+2"]; NSAssert([result isEqualToString:@"3"], @"correct, but strings are kind of unsatisfying");
webView:shouldStartLoadWithRequest:navigationType
.The landscape changed a few months ago when Apple quietly introduced a new Objective-C JavaScriptCore wrapper into WebKit, resembling a modernized version of the Mac WebScriptObject classes. This breakthrough offered powerful capabilities on both Mac and iOS platforms, enabling seamless interaction between JavaScript and Objective-C.While the API became publicly available in iOS7, it faced challenges, notably being undocumented and lacking details on obtaining a JSContext from a UIWebView. Developers resorted to KVO-compliant approaches, addressing the limitations and allowing the combination of JavaScriptCore bindings with the flexibility of UIWebView content.Despite these advancements, documentation remains scarce, and developers have had to explore header files and source code to grasp the full potential of the new API. Nevertheless, the possibilities introduced by this Objective-C JavaScriptCore wrapper hold great promise for hybrid apps seeking effective interoperability between JavaScript and Objective-C.