HTTP-запрос через JavaScriptCore в iOS7

Я пытаюсь использовать одну из новых функций iOS7, JavaScriptCore Framework. Я могу успешно вывести строку helloWorld из Javascript, но меня интересует выполнение HTTP POST в Javascript, а затем передача ответа в Objective-C. К сожалению, когда я создаю объект XMLHttpRequest в Javascript, я получаю 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";
};

Вот код Objective-C внутри моего ViewController:

- (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:@[]];
}

Может ли быть так, что функциональность HTTP-запросов не предусмотрена в JavaScriptCore Framework? Если да, могу ли я преодолеть это, используя -stringByEvaluatingJavaScriptFromString: UIWebView? Что, если я скомпилирую и включу в свой проект другой Javascript Engine (например, V8)?


person Kostis    schedule 18.11.2013    source источник


Ответы (2)


Я предполагаю, что HTTP-запросы не являются частью ядра JavaScript, поскольку на самом деле они являются частью браузера, а не языка JavaScript.
Я бы предположил, что ядро ​​JavaScript включает только то, что находится в определении ECMAScript.

Если вам нужен AJAX, тогда вам подойдет WebView.

person Ben Clayton    schedule 18.11.2013
comment
Спасибо Бен за помощь! Я ценю это. Я надеялся, что эта новая функция iOS7 будет по-настоящему мощной, но, по-видимому, это не так :( Похоже, что XMLHttpRequest существует в какая-нибудь черновая версия. И если я не уверен, что UIWebView подходит, мне придется прибегнуть к неприятные хаки и иметь накладные расходы UIWebView, когда мне нужно только выполнить Javascript. Но в любом случае, поскольку я не вижу другого решения к этому ... Спасибо, Бен :) - person Kostis; 19.11.2013
comment
Нет проблем. Я рекомендую просто кусать пулю и вместо этого использовать AFNetworking для вашего POST-запроса. - person Ben Clayton; 19.11.2013
comment
fetch() еще не придумали? - person vicentedealencar; 24.09.2015

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]];
        } 
    }];
}

Затем привяжите экземпляр к JContext где-нибудь в вашем коде.

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

из вашего JS-файла теперь вы можете вызвать

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

Вы также можете использовать блок и привязать его прямо к JContext, чтобы получить тот же результат.

person Manuel Spuhler    schedule 30.01.2014
comment
Как получить данные данных из обратного вызова js для моей цели c - person Codesen; 21.01.2015
comment
на swift context["utils"] = JSUtils() Тип 'JSContext' не имеет элементов нижнего индекса. как это работало в быстром? - person EvGeniy Ilyin; 22.11.2018
comment
Свифт context.setObject(JSUtils.self, forKeyedSubscript: "utils" as NSString) - person EvGeniy Ilyin; 22.11.2018