Как вызвать метод Objective C из Javascript и отправить обратно данные в Javascript в iOS? - PullRequest
31 голосов
/ 22 марта 2012

В iOS, как я могу вызвать метод Objective C из Javascript в UIWebView и заставить его отправлять данные обратно в Javascript? Я знаю, что это можно сделать на OS X с помощью библиотеки Webkit, но возможно ли это на iOS? Как PhoneGap достигает этого?

Ответы [ 3 ]

64 голосов
/ 22 марта 2012

Существует 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.)

11 голосов
/ 23 июня 2013

Изменение местоположения страницы может вызвать несколько проблем :

  1. Все setInterval и setTimeout немедленно останавливаются при изменении местоположения
  2. Каждый innerHTML не будет работать после отмены изменения местоположения!
  3. Вы можете получить другие действительно странные ошибки, очень трудно диагностировать ...

Решение, как предлагается здесь , это:

Продолжайте использовать ту же технику URL (на js и target-c), просто измените местоположение с помощью iframe:

 var iframe = document.createElement("IFRAME");
 iframe.setAttribute("src", "js-frame:myObjectiveCFunction";
 document.documentElement.appendChild(iframe);
 iframe.parentNode.removeChild(iframe);
 iframe = null;

Надеюсь, что поможет

5 голосов
/ 22 марта 2012

Из 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"; </script>

Перехватить запрос URL

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...