无法在 JavaScriptCore JSContext 中 运行 proj4.js

Unable to run proj4.js in JavaScriptCore JSContext

我一直无法 运行 proj4.js(投影 Javascript、http://proj4js.org)iOS Objective-C JavaScript核心JS上下文。在上下文中尝试 运行 之后,proj4 函数对我在同一 JSContext 中尝试 运行 的后续 Javascript 代码不可用。

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

时出现以下异常

TypeError: undefined is not an object (evaluating '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()

所以这表明 'window'、'global' 和 'self' 都没有在 JSContext 环境中定义(我认为?)。我是 JavaScriptCore 的新手(并且是 JavaScript 的新手),所以我不确定从这里到哪里去(但我会继续研究)。

根据对我的问题的编辑,'window'、'global' 和 'self' 似乎都没有在新的 JSContext 中定义。这对 'window' 有意义(对 'global' 或 'self' 不太确定!!!)。

所以我想到了两个可能的修复方法:

  1. 第一个修复适用于 proj4.js,但不适用于我需要 运行 的后续两个 JavaScript。此修复是在尝试 运行 proj4.js:

    之前简单地添加以下行 Objective-C 代码
    [context evaluateScript:@"var global = this;"];
    

然后是问题行(原问题中我原代码的最后一行)运行没问题!

  1. 此修复更全面,因为它应该适用于任何可以在普通网络浏览器中 运行 的 JavaScript。然而,它的手头更重。对于此解决方案,唯一需要更改的是替换 JSContext 'init' 行以从 UIWebView 获取 JSContext:

    JSContext * context = [[[UIWebView alloc] init] valueForKeyPath : @"documentView.webView.mainFrame.javaScriptContext" ];
    

虽然我更愿意避免实例化 Web 视图,但缺少的组件太多,无法将原始 JSContext 用于复杂的 Javascript。我也更喜欢使用 WKWebView 而不是 UIWebView,但是目前,WKWebView 的 JSContext 不可用。