I am trying to use one of iOS7 new features, the JavaScriptCore Framework. I can successfully output a helloWorld string from Javascript, but what I'm interested in, is doing HTTP POSTs in Javascript and then pass the response to Objective-C. Unfortunately, when I'm creating an XMLHttpRequest
object in Javascript, I get EXC_BAD_ACCESS (code=1, address=....)
.
Here is the Javascript code (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";
};
Here is the Objective-C code inside my 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:@[]];
}
Could it be that HTTP Requests functionality is not provided in JavaScriptCore Framework? If yes, could I overcome this by using UIWebView
's -stringByEvaluatingJavaScriptFromString:
? What if I compiled and included in my project another Javascript Engine (e.g. V8)?
XMLHttpRequest is, as stated before, not part of JavaScript, but you still can wrap the iOS URLRequest so it's available in your JS.
in JSUtils.h
@protocol UtilsExport;
@interface JSUtils : NSObject <UtilsExport>
@end
@protocol UtilsExport <JSExport>
- (void)get:(NSString *)url then:(JSValue *)jsCallback;
@end
in 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]];
}
}];
}
Next, bind the instance to the JSContext somewhere in your code
JSContext *context = [[JSContext alloc] init];
context[@"utils"] = [[JSUtils alloc] init];
from your JS file, you can now call
utils.getThen('http://localhost/api/dashboard', function(resultString){
console.log(resultString)
}
You could also use a block and bind it straight to the JSContext to get the same result.
My guess would be that HTTP Requests are not part of JavaScript Core, as it's really part of the browser, not the JavaScript Language.
I would assume that JavaScript core only includes what's in the ECMAScript definition.
If you want AJAX, then the WebView is the way to go.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With