【问题标题】:HTTP Request through JavaScriptCore in iOS7iOS7中通过JavaScriptCore的HTTP请求
【发布时间】:2013-11-18 16:42:00
【问题描述】:

我正在尝试使用 iOS7 的一项新功能,即 JavaScriptCore 框架。我可以从 Javascript 成功输出 helloWorld 字符串,但我感兴趣的是在 Javascript 中执行 HTTP POST,然后将响应传递给 Objective-C。不幸的是,当我在 Javascript 中创建 XMLHttpRequest 对象时,我得到了 EXC_BAD_ACCESS (code=1, address=....)

这里是 Javascript 代码 (hello.js):

var sendSamplePost = function () {
    // when the following line is commented, everything works,
    // if not, I get EXC_BAD_ACCESS (code=1, address=....)
    var xmlHttp = new XMLHttpRequest();
};

var sayHello = function (name) {
    return "Hello " + name + " from Javascript";
};

这是我 ViewController 中的 Objective-C 代码:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    JSContext *context = [[JSContext alloc] initWithVirtualMachine:[[JSVirtualMachine alloc] init]];

    NSString *scriptPath = [[NSBundle mainBundle] pathForResource:@"hello" ofType:@"js"];
    NSLog(@"scriptPath: %@", scriptPath);
    NSString *script = [NSString stringWithContentsOfFile:scriptPath encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"script: %@", script);

    [context evaluateScript:script];

    JSValue *sayHelloFunction = context[@"sayHello"];
    JSValue *returnedValue = [sayHelloFunction callWithArguments:@[@"iOS"]];

    // this works!
    self.label.text = [returnedValue toString];


    JSValue *sendSamplePostFunction = context[@"sendSamplePost"];

    // this doesn't work :(
    [sendSamplePostFunction callWithArguments:@[]];
}

会不会是 JavaScriptCore 框架中没有提供 HTTP 请求功能?如果是,我可以通过使用UIWebView-stringByEvaluatingJavaScriptFromString: 来克服这个问题吗?如果我在我的项目中编译并包含另一个 Javascript 引擎(例如 V8)怎么办?

【问题讨论】:

    标签: ios objective-c httprequest javascriptcore


    【解决方案1】:

    如前所述,XMLHttpRequest 不是 JavaScript 的一部分,但您仍然可以包装 iOS URLRequest,以便在您的 JS 中使用它。

    在 JSUtils.h 中

       @protocol UtilsExport;
    
       @interface JSUtils : NSObject <UtilsExport>
       @end
    
       @protocol UtilsExport <JSExport>
       - (void)get:(NSString *)url then:(JSValue *)jsCallback;
       @end
    

    在 JSUtils.m 中

    #import "JSUtils.h"
    
    - (void)get:(NSString *)url then:(JSValue *)callback {
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                               cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
                                                           timeoutInterval:10];
        [request setHTTPMethod:@"GET"];
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            if ([data length] > 0 && error == nil) {
                [callback callWithArguments:@[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding], @YES]];
            } 
        }];
    }
    

    接下来,将实例绑定到代码中某处的 JSContext

    JSContext *context = [[JSContext alloc] init];
    context[@"utils"] = [[JSUtils alloc] init];
    

    从你的 JS 文件中,你现在可以调用

    utils.getThen('http://localhost/api/dashboard', function(resultString){
      console.log(resultString)
    }
    

    您也可以使用块并将其直接绑定到 JSContext 以获得相同的结果。

    【讨论】:

    • 如何从 js 回调中获取数据数据到我的目标 c
    • on swift context["utils"] = JSUtils() 类型 'JSContext' 没有下标成员。它是如何快速运行的?
    • 斯威夫特context.setObject(JSUtils.self, forKeyedSubscript: "utils" as NSString)
    【解决方案2】:

    我的猜测是 HTTP 请求不是 JavaScript 核心的一部分,因为它实际上是浏览器的一部分,而不是 JavaScript 语言。
    我会假设 JavaScript 核心只包含 ECMAScript 定义中的内容。

    如果你想要 AJAX,那么 WebView 就是你要走的路。

    【讨论】:

    • 感谢本的帮助!我很感激。我希望这个新的 iOS7 功能真的很强大,但显然它不是 :( XMLHttpRequest 似乎存在于some draft version 中。如果我不确定 UIWebView 是 要走的路,因为当我只需要执行 Javascript 时,我将不得不求助于nasty hacks 并拥有 UIWebView 开销。但无论如何,因为我没有看到任何其他解决方案......谢谢 Ben :)
    • 没有问题。我建议只是咬紧牙关,使用 AFNetworking 代替您的 POST 请求。
    • 还不是fetch() 吗?
    【解决方案3】:
    JSContext *context = [[JSContext alloc] init];
    
    context[@"request"] = ^(NSString *url) {
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                           cachePolicy:NSURLRequestReloadIgnoringCacheData
                                                       timeoutInterval:10];
    
        NSURLResponse *response = nil;
    
        [request setHTTPMethod:@"GET"];
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
        NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        return body;
    };
    

    在 JS 中:

    var body = request(url);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-07
      • 2014-08-19
      • 2011-09-28
      • 1970-01-01
      • 1970-01-01
      • 2012-07-30
      • 2013-01-15
      • 2011-12-13
      相关资源
      最近更新 更多