В iOS, как я могу вызвать метод Objective-C из Javascript в UIWebView
и отправить его обратно в Javascript? Я знаю, что это можно сделать в OS X, используя библиотеку Webkit, но возможно ли это на iOS? Как PhoneGap достигает этого?
Как вызвать метод Objective C из Javascript и отправить данные в Javascript в iOS?
Ответ 1
Существует API для вызова JavaScript непосредственно из Objective-C, но вы не можете вызвать Objective-C непосредственно из Javascript.
Как сообщить вашему коду Objective-C что-то сделать из Javascript в вашем WebView
Вы должны сериализовать действие Javascript в специальный URL-адрес и перехватить этот URL-адрес в делететом shouldStartLoadWithRequest
в интерфейсе UIWebView.
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType;
Здесь вы можете десериализовать этот специальный URL-адрес и интерпретировать его, чтобы сделать то, что вы хотите на стороне Objective-C. (Вы должны вернуть NO
в приведенном выше методе shouldStartLoadWithRequest
, чтобы UIWebView не использовал ваш фиктивный URL, чтобы фактически сделать HTTP-запрос для загрузки веб-страницы.)
Как запустить Javascript-код из Objective-C
Затем вы можете запустить Javascript из Objective-C, вызвав этот метод в своем веб-просмотре.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
Пример кода
Я рекомендую использовать схему фиктивных URL-адресов, поэтому будет легко рассказать о разнице между вашими действительными URL-адресами и законными запросами. Вы можете сделать этот запрос в Javascript в следующих строках:
// JavaScript to send an action to your Objective-C code
var myAppName = 'myfakeappname';
var myActionType = 'myJavascriptActionType';
var myActionParameters = {}; // put extra info into a dict if you need it
// (separating the actionType from parameters makes it easier to parse in ObjC.)
var jsonString = (JSON.stringify(myActionParameters));
var escapedJsonParameters = escape(jsonString);
var url = myAppName + '://' + myActionType + "#" + escapedJsonParameters;
document.location.href = url;
Затем в методе UIWebView.delegate
shouldStartLoadWithRequest
вы можете проверить схему и фрагмент URL, чтобы проверить, является ли это обычным запросом или одним из ваших специальных действий. (Фрагмент URL - это то, что приходит после #
.)
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
// these need to match the values defined in your JavaScript
NSString *myAppScheme = @"myfakeappname";
NSString *myActionType = @"myJavascriptActionType";
// ignore legit webview requests so they load normally
if (![request.URL.scheme isEqualToString:myAppScheme]) {
return YES;
}
// get the action from the path
NSString *actionType = request.URL.host;
// deserialize the request JSON
NSString *jsonDictString = [request.URL.fragment stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
// look at the actionType and do whatever you want here
if ([actionType isEqualToString:myActionType]) {
// do something in response to your javascript action
// if you used an action parameters dict, deserialize and inspect it here
}
// make sure to return NO so that your webview doesn't try to load your made-up URL
return NO;
}
(прочитайте этот ответ, если вам нужна помощь, десериализируя вашу строку json в NSDictionary.)
Ответ 2
Изменение местоположения страницы может вызвать несколько вопросов:
- Все setInterval и setTimeout немедленно останавливаются при изменении местоположения
- Каждый innerHTML не работает после отмены изменения местоположения!
- Вы можете получить другие действительно странные ошибки, очень трудно диагностировать...
Решение, предложенное здесь, следующее:
Продолжайте использовать тот же метод URL (на js и objective-c), просто измените местоположение с помощью iframe:
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "js-frame:myObjectiveCFunction";
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
Надеюсь, что поможет
Ответ 3
Из Objective-C: вы можете передать функцию javascript в строке в UIWebView. Веб-страница выполнит его и вернет результат. Таким образом, вы можете передавать переменные и получать данные из Javascript.
- (NSString *) stringByEvaluatingJavaScriptFromString: (NSString *) script
Код>
Пример:
NSString * script = @ "document.getElementById('myTextField'). value";
NSString * output = [myWebView stringByEvaluatingJavaScriptFromString: script];
Код>
Из Javascript: передайте свои данные внутри URL-адреса. Перехват запросов URL в UIWebViewDelegate. Получите данные и прервите запрос URL, вернув NO.
<script> window.location = "url://key1/value1"; </сценарий >
Код>
- (BOOL) webView: (UIWebView *) webView shouldStartLoadWithRequest: (NSURLRequest *) request navigationType: (UIWebViewNavigationType) navigationType
Код>