Всем привет, мы снова встретились, я ваш друг Цюаньчжаньцзюнь.
iOS JSиOCвзаимодействие
UIWebView
JS и OC взаимодействиеUIWebView
существовать iOS12 серединаужеодеялозаброшенный,в то же времяWKWebView
существоватьiOS8серединаужеПоявляться。Так что особых обстоятельств нетизразговаривать,Мы должны вообщедаБывший больше не нужен!
UIWebView
по сравнению с WKWebView
Пользоваться будет гораздо проще.
UIWebView
инициализация:
self.webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
self.webView.delegate = self;
[self.view addSubview:self.webView];
// Загрузить локально H5 документ
NSURL *url = [[NSBundle mainBundle] URLForResource:@"index.html" withExtension:nil];
NSURLRequest *reqeust = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:reqeust];
Семейное ведро Jetbrains 1 год 46, стабильная послепродажная гарантия
UIWebViewDelegate
протоколизнесколькометод:
// перехватыватьJS запрос операции страницы, JS вызовOC Используется, когда метод
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
// Начать загрузку страницы
- (void)webViewDidStartLoad:(UIWebView *)webView;
// Страница загружена
- (void)webViewDidFinishLoad:(UIWebView *)webView;
// Загрузка страницы не удалась
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;
OC вызывает функции JS двумя способами:
①использовать
stringByEvaluatingJavaScriptFromString
,Сращивание JS Строковый вызов. ②Использование JSContext контекстный вызов JS функция
Первый метод относительно прост в использовании, но не может быть реализован для сложных предприятий.
JS-код выглядит следующим образом:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OCиJSвзаимодействие</title>
<script>
function showAlert_hasReturnValue(str){
alert('OC вызовJS ' + str);
return 'Возвратить значение в OC';
}
function showAlert_noReturnValue(str){
alert('OC вызовJS ' + str);
}
</script>
</head>
</html>
OC позвонить JS Функция – это общая JS объединены в строку, как stringByEvaluatingJavaScriptFromString
Параметры метода реализованы.
/** OC вызов JS Нет возвращаемого значения */
- (IBAction)didClickLeftItem:(id)sender {
[self.webView stringByEvaluatingJavaScriptFromString:@"showAlert_noReturnValue('Нет возвращаемого значения')"];
}
/** OC вызов JS Есть возвращаемое значение */
- (IBAction)didClickRightItem:(id)sender {
// OC --> JS Есть возвращаемое значение
NSString *resString = [self.webView stringByEvaluatingJavaScriptFromString:@"showAlert_hasReturnValue('Есть возвращаемое значение')"];
NSLog(@"%@", resString);
}
Когда UIWebView загружен, инициализируйте контекстную среду:
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.context = context;
}
#pragma mark - ответ
/** OC вызов JS Нет возвращаемого значения */
- (IBAction)didClickLeftItem:(id)sender {
NSDictionary *dict = @{@"name": @"kangpp", @"age": @28};
// контекстный вызов JS функция
[self.context[@"ocCallJS_byJSContext"] callWithArguments:@[dict]];
}
JS вызов OC Существует три способа реализации функции:
①
webView: shouldStartLoadWithRequest:
протоколсерединаперехватывать JS действовать. ② использовать JavaScriptCore, чтобы JS Зарегистрируйтесь в OC Классы,JS функциясерединапрямойвызов OC метод. ③ использовать JSContext Контекст, JS перезвонить OC кодовый блок.
HTML документсередина,нуждатьсявызов OC тег методиз, добавьте атрибуты гиперссылки (протокол гиперссылки можно настроить). Тогда тег действия будет существовать UIWebViewDelegate
протоколметод - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
было перехвачено мониторингом.
JS Файлы следующие:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OCиJSвзаимодействие</title>
<script>
</script>
</head>
<body>
<div>
<a href="kpp://jsCallOC:/helloword/js">JS вызов OC метод (метка операции будет OC перехватывать)
</a>
</div>
</body>
</html>
при нажатии <a>
При маркировке,существовать нижепротоколметодсерединаМы начнем сrequest
серединаполучатьURLинформация:
#pragma mark - UIWebViewDelegate
// Загрузить все данные запроса и контролировать, следует ли загружать
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
// URL ==> kpp://jsCallOC:/helloword/js
NSURL *requestURL = request.URL;
// URL Общий формат из: scheme://host:port/path?
NSString *scheme = requestURL.scheme;
NSString *host = requestURL.host;
NSNumber *port = requestURL.port;
NSArray *paths = requestURL.pathComponents;
// URL строка полного пути
NSString *absoluteString = requestURL.absoluteString;
// Относительный путь после порта
NSString *path = requestURL.path;
return YES;
}
Согласно вышеизложенному из URL середина Получить из данных, вы можете сохранить этот вызов настройки маршрута OC середина указывает изметод. Посылка заключается в том, что мы должны достичь консенсуса между собой. URL Формат данных.
#pragma mark - UIWebViewDelegate
// Загрузить все данные запроса и контролировать, следует ли загружать
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
// request : host + маршрутизация : перехватывать
if ([request.URL.scheme isEqualToString:@"kpp"]) {
// методимя kpp://jsCallOC:/helloword/js
NSString *routerName = request.URL.host;
SEL methodSEL = NSSelectorFromString(routerName);
// Метод испытания для jsCallOC
NSLog(@"routerName => %@", routerName);
if ([self respondsToSelector:methodSEL]) {
objc_msgSend(self,methodSEL,@"");
} else {
NSLog(@"Соответствующий метод измаршрутизации" не найден);
}
return NO;
}
return YES;
}
/** JS вызов OC изответметод */
- (void)jsCallOC {
NSLog(@"JSвызовизметод!");
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"намекать" message:@"JSвызовOCметод" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
[controller addAction:okAction];
[self presentViewController:controller animated:YES completion:nil];
}
К JS инъекция OC класс, надо представить <JavaScriptCore/JavaScriptCore.h>
рамка,использовать JSContext
К JS серединаинъекция OC добрый.
В то же время, будучи JS вызовиз OC необходимо следовать методам JSExport
протокол。
Например, требование JS вызов OC из getUserInfo
Метод получения информации о пользователе внутри приложения.
первый,поставить этометодиспользоватьпротоколСоглашение,и наследоватьJSExport
протокол:
@protocol TestProtocol <JSExport>
- (NSString *)getUserInfo;
@end
ЗатемсуществоватьинъекцияJSиздобрыйсерединаподчинятьсяTestProtocol
протоколи реализовать getUserInfo
метод , демосередина существует непосредственно в реализации контроллера:
@interface ViewController ()<UIWebViewDelegate, TestProtocol>
@property (nonatomic, strong) UIWebView *webView;
@end
когда Когда UIWebView загружен,использоватьJSContext
К WebView серединаинъекцияOCдобрый:
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// Это может быть объект экземпляра или объект
context[@"ViewController"] = self;
}
соответствующийизсуществоватьJS середина,Можетпрямойиспользовать OC добрыйиметодвызов:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OCиJSвзаимодействие</title>
<script>
function getUserInfo() {
// инъекция OCдобрый, здесь можно напрямую вызвать через имя OCдобрый
var val = ViewController.getUserInfo();
alert(val);
}
</script>
</head>
<body>
<input type="button" value="инъекцияOCдобрыйизСпособ вызовите OCметод и получите возвращаемое значение" onClick="getUserInfo()" />
</body>
</html>
JS кодсерединаblockOCCode()
СразудаосуществлятьизOCблок код, следующий:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OCиJSвзаимодействие</title>
<script>
function jsCallOC_byJSContext() {
// arr да OC инъекцияиз глобальных атрибутов, которые можно обработать здесь и передать в OC
// Для атрибута инъекцияиз верните его в OC
arr.splice(0, 1)
blockOCCode(arr)
}
</script>
</head>
<body>
<input type="button" value="JS вызов OC метод(JS перезвонить OCBlock блок кода)" onClick="jsCallOC_byJSContext()" />
</body>
</html>
Та же причина,существоватьOCкодсередина,когда Страница загружена,СразухотетьполучатьконтекстизЦитировать,инъекцияСвойства иblockOCCode
Назначение блока кода:
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// получать JS контекстная ссылка
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.context = context;
self.context[@"ViewController"] = self;
// js серединаинъекцияглобальные переменные [context evaluateScript:@"var arr = ['Чжан Сан', «Джон Доу»,'Ван Ву', 'Чжао Лю']"];
context[@"blockOCCode"] = ^(NSArray *jsArr){
// jsArr да JS перешел к OCблок параметры кодирования
NSLog(@"blockOCCode->jsArr == %@", jsArr);
// проходитьконтекстполучать JS глобальные свойства
//NSArray *orgArr = [JSContext currentArguments];
//NSLog(@"blockOCCode->orgArr == %@", orgArr);
};
}
Этого можно достичь JS перезвонить OC кодовый блок.
Код сбора исключений JS:
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// Сбор исключений
self.context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
NSLog(@"%@",exception);
};
}
WKWebView
OC и JS взаимодействиеWKWebView
инициализация:
// Конфигурациядобрый WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
// Адаптировано для мобильных устройств
NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
[wkUController addUserScript:wkUScript];
configuration.userContentController = wkUController;
// инициализация WebView
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
// <WKUIDelegate, WKNavigationDelegate>
self.webView.UIDelegate = self;
self.webView.navigationDelegate = self;
[self.view addSubview:self.webView];
// Загрузка (локальная) H5 документ
NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"WKWebView_Index.html" ofType:nil];
NSURL *fileURL = [NSURL fileURLWithPath:urlStr];
[self.webView loadFileURL:fileURL allowingReadAccessToURL:fileURL];
WKUIDelegate
протоколЭтот протокол часто используется для замены всплывающих подсказок JS для улучшения взаимодействия с пользователем.
// Создать новый из WebView Посмотреть вызов времени
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
// Когда представление закрыто, вызов
- (void)webViewDidClose:(WKWebView *)webView;
// JS Вызов окна с предупреждением
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
// JS Окно подтверждения вызова
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
// JS функция Prompt(), метод будет выполнен
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
OC вызов JS передано evaluateJavaScript: completionHandler:
реализация методаиз,JS Код относительно прост:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OCиJSвзаимодействие</title>
<script>
function ocCallJS(str) {
alert("OC ---> JS" + str);
<!-- return value проходить evaluateJavaScript: completionHandler: перезвонитьсерединаизценитьперешел кOC -->
return "ocCallJS return value";
}
</script>
</head>
</html>
Код OC тоже не сложен:
/** OC вызов JS возвращатьсяценитьсуществовать completionHandler изперезвонитьпараметр result внутри */
- (IBAction)didClickRightItem:(id)sender {
// OC --> JS Есть возвращаемое значение
NSString *jsStr = @"ocCallJS('WK_ocCallJS:OC-->JS')";
[self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
// result да JS return вернуть значение
NSLog(@"%@----%@",result, error);
}];
}
WKWebView середина JS вызов OC Существует два способа реализации функции:
① использовать
WKNavigationDelegate
протоколwebView: decidePolicyForNavigationAction: decisionHandler:
методперехватывать JS Запрос операции. ② использоватьWKScriptMessageHandler
протоколuserContentController: didReceiveScriptMessage:
метод,перенимать JS Отправьте конкретное сообщение для анализа и обработки.
HTML документсередина,нуждатьсявызов OC тег методиз, добавьте атрибуты гиперссылки (протокол гиперссылки можно настроить). Тогда тег действия будет существовать WKNavigationDelegate
протоколметод - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
было перехвачено мониторингом.
JS Код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OCиJSвзаимодействие</title>
</head>
<body>
<div>
<a href="kpp://WKWebView_jsCallOC:/helloword/js"> WK позвонитьOC </a>
<div/>
<br />
</body>
</html>
OC серединаперехватывать,ииспользоватьмаршрутизациявызовобозначение OC метод:
#pragma mark - WKNavigationDelegate
// перехватывать JS кодсерединаиз запросить операцию
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if ([navigationAction.request.URL.scheme isEqualToString:@"kpp"]) {
NSString *routerName = navigationAction.request.URL.host;
SEL methodSEL = NSSelectorFromString(routerName);
NSLog(@"routerName => %@", routerName);
if ([self respondsToSelector:methodSEL]) {
objc_msgSend(self,methodSEL,@"");
} else {
NSLog(@"Нетсоответствующиймаршрутизация");
}
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
// одеяло JS вызовиз OC метод
- (void)WKWebView_jsCallOC {
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"намекать" message:@"WK серединаJSвызовOCметод" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
[controller addAction:okAction];
[self presentViewController:controller animated:YES completion:nil];
}
Шаги по методиспользованию относительно утомительны, но WKScriptMessageHandler
протоколсерединатолько одинметодuserContentController: didReceiveScriptMessage:
① представлять WKScriptMessageHandler протокол,ииспользовать config инициализация WKWebView。
② зарегистрироваться ScriptMessageHandler
。
③ выполнитьпротоколметод. ④ Удалять ScriptMessageHandler
JS Код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OCиJSвзаимодействие</title>
<script>
function jsSendMessage(){
// js отправить сообщение, messgaeToOC дасуществовать OC кодЗарегистрируйтесь виз Имя
var val = window.webkit.messageHandlers.messgaeToOC.postMessage("js отправить в OC из Сообщение");
alert(val);
}
</script>
</head>
<body>
<div>
<input type="button" value="messgaeHandle" onClick="jsSendMessage()" />
<div/>
<br />
</body>
</html>
Этапы реализации кода OC:
// ① представлятьпротокол
@interface KYWKContorller ()<WKScriptMessageHandler>
// ② имя обработки сообщения зарегистрироваться:messgaeToOC
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"messgaeToOC"];
}
// ③ выполнитьпротоколметод
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
// message.name Сразуданасзарегистрироватьсяиз messgaeToOC
// message.body СразудаJSОтправитьизинформация
NSLog(@"%@---%@",message.name, message.body);
// По этим двум параметрам Напишите наш бизнес-код
... ...
}
// ④ Когда контроллер уничтожен Удалять `ScriptMessageHandler`
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"messgaeToOC"];
}
WebViewJavascriptBridge
Использование библиотекиВведение в этот разделизСторонние библиотекида:WebViewJavascriptBridge。
Эта библиотека поддерживает UIWebView
иWKWebView
。использоватьотносительно простой,Легко начать.
Шаги, которые нужно сделать:
① представлятьголовадокумент ② инициализация моста добрый экземпляр ③ (JS вызов OC)OCсередина
registerHandler
зарегистрироватьсяJSметод,использоватьblockпередачаперезвонить;( OC вызов JS)callHandler
вызов JS метод,использоватьblockперезвонитьJSВозврат результатов。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OCиJSвзаимодействие</title>
<script>
<!-- использоватьБиблиотека,JS серединакодсерединануждатьсядобавить в:-->
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
setupWebViewJavascriptBridge(function(bridge) {
// JS одеяловызовизметод OCCallJSFunction Определение логотипа
bridge.registerHandler('OCCallJSFunction', function(data, responseCallback) {
alert('JSметододеяловызов:' + data);
responseCallback('OCвызовизJSметодужеодеялоосуществлять');
})
})
function jsCallsOCFunc(){
WebViewJavascriptBridge.callHandler('jsCallsOC', {'name': 'kpp'}, function(response) {
alert(response);
})
}
</script>
</head>
<body>
<div>
<input type="button" value="JS вызов OC метод" onclick="jsCallsOCFunc()" /> <br />
<div/>
<br />
<div>
<a href="kpp://WKWebView_jsCallOC:/helloword/js"> WK позвонитьOC (Нетиспользоватьтретья сторона) </a>
<div/>
<br />
</body>
</html>
Реализация кода OC:
#import "WebViewJavascriptBridge.h"
@property (strong, nonatomic) WKWebView *webView;
@property (nonatomic, strong) WebViewJavascriptBridge *wjb;
- (void)createWjb {
// инициализация моста добрый экземпляр
self.wjb = [WebViewJavascriptBridge bridgeForWebView:self.webView];
// настраивать WKNavigationDelegate Агенты, те, кто сохранит этот протоколиспользовать, все еще доступны.
[self.wjb setWebViewDelegate:self];
}
/** JS вызов OC метод */
- (void)jsCallOC {
// JS-->OC
[self.wjb registerHandler:@"jsCallsOC" handler:^(id data, WVJBResponseCallback responseCallback) {
// data да JS перешел кOC из параметра responseCallback может выдать результат выполнения, перезвонить на JS
NSLog(@"%@---%@----%@",[NSThread currentThread],data,responseCallback);
responseCallback(@"JSвызовизOCметод выполнен");
}];
}
/** OC вызов JS метод */
- (void)OCCallJS {
[self.wjb callHandler:@"OCCallJSFunction" data:@"Передать параметр параметра" responseCallback:^(id responseData) {
// data да OC перешел к JS изпараметр,responseDataда JS После завершения исполнения перезвонить будет передан OC. из Результаты выполнения
NSLog(@"%@--%@",[NSThread currentThread],responseData);
}];
}
Заявление об авторских правах: Содержание этой статьи добровольно предоставлено пользователями Интернета.,Мнения, выраженные в данной статье, принадлежат исключительно автору. Этот сайт предоставляет только услуги по хранению информации.,нет собственности,Никакая соответствующая юридическая ответственность не предполагается. Если на этом веб-сайте есть какое-либо подозрение на нарушение авторских прав/незаконный контент,, Пожалуйста, отправьте электронное письмо на Сообщите, после проверки этот сайт будет немедленно удален.
Издатель: Full stack программист и руководитель стека, укажите источник для перепечатки: https://javaforall.cn/206864.html Исходная ссылка: https://javaforall.cn