无法在JavaScriptCore JSContext

时间:2016-11-05 07:48:38

标签: javascript ios objective-c cocoa javascriptcore

我无法在iOS Objective-C JavaScriptCore JSContext中运行proj4.js(投影Javascript,http://proj4js.org)。尝试在上下文中运行它后,proj4函数不能用于我尝试在同一个JSContext中运行的后续Javascript代码。

在JSContext上启用Javascript异常处理后,我发现在尝试运行proj4.js时出现以下异常:

  

TypeError:undefined不是对象(评估' b.proj4 = a()')

我已经通过一些加载脚本的HTML在WKWebView中成功运行了相同的proj4.js。那里工作得很好。但我现在需要它在JSContext中运行,我在其中使用它并将对象从Javascript输出转换为Objective-C对象。

这里的代码失败了:

    NSString *proj4Path = [[NSBundle mainBundle] pathForResource:@"proj4" ofType:@"js" inDirectory:@"proj4"];
    NSString *proj4JS = [NSString stringWithContentsOfFile:proj4Path usedEncoding:nil error:nil];
    JSContext *context = [[JSContext alloc] init];
    context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
        NSLog(@"JAVASCTIPT EXCEPTION: %@", exception);
    };
    [context evaluateScript:proj4JS];  //  FAILS HERE

如果我用一个非常简单的JavaScript替换最后一行,它可以正常工作。例如,

[context evaluateScript:@"1 + 1"];

因此看起来上下文本身是有用的。也许JSContext的环境或配置存在一些问题,但我无法想到任何事情。

编辑:导致异常的proj4.js中的行是:

"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.proj4=a()

所以这表明两个窗口都没有'也不是全球的'也不是' self'在JSContext环境中定义(我认为?)。我是JavaScriptCore的新手(也是JavaScript的新手),所以我不确定从哪里开始(但我会继续研究)。

1 个答案:

答案 0 :(得分:1)

根据我的问题的编辑,没有'窗口'也不是全球的'也不是' self'似乎是在新的JSContext中定义的。这对于“窗口”来说是有意义的。 (不太确定' global'或者' self' !!!)。

因此我提出了两种可能的修复方法:

  1. 第一个修复程序适用于proj4.js,但不适用于我需要运行的两个后续JavaScripts。这个修复是在尝试运行proj4.js之前简单地添加以下的Objective-C代码:

    [context evaluateScript:@"var global = this;"];
    
  2. 然后问题行(原始问题中原始代码的最后一行)运行正常!

    1. 此修复程序更全面,因为它适用于任何可以在普通Web浏览器中运行的JavaScript。但是,它更加笨拙。对于此解决方案,唯一需要的更改是替换JSContext' init'从UIWebView获取JSContext的行:

      JSContext * context = [[[UIWebView alloc] init] valueForKeyPath : @"documentView.webView.mainFrame.javaScriptContext" ];
      
    2. 虽然我更喜欢避免实例化Web视图,但是对于复杂的Javascripts,使用原始JSContext的组件太多了。我也更喜欢使用WKWebView而不是UIWebView,但目前,WKWebView的JSContext不可用。