IOS7のJavaScriptCoreを介したHTTPリクエスト
-
27-12-2019 - |
質問
JavaScriptCoreフレームワークのiOS7新機能の1つを使用しようとしています。私はJavaScriptからHelloWorld文字列を正常に出力できますが、私が興味があるのはJavaScriptでHTTP投稿をしてから、その応答を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";
};
.
これは、My 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:@[]];
}
.
HTTPリクエスト機能はJavaScriptCoreフレームワークで提供されていませんか。もしそうなら、UIWebView
の-stringByEvaluatingJavaScriptFromString:
を使用してこれを克服できますか?私がコンパイルして私のプロジェクトに含まれている場合は、別のJavaScriptエンジン(例えば、v8)?
解決
私の推測は、JavaScript言語ではなく、ブラウザの一部であるため、HTTPリクエストはJavaScriptコアの一部ではないということでしょう。
JavaScriptコアでは、ECMAScript定義内のものだけが含まれていると仮定します。
ajaxが欲しいのなら、WebViewは行く方法です。
他のヒント
XMLHTTPRequestは、前述のように、JavaScriptの一部ではなく、あなたはそれがあなたのJSで利用可能であるようにiOS URLRequestをラップすることができるようにまだ描くことができます。 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にまっすぐにバインドして同じ結果を得ます。
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);
.