iOS原生与H5交互方法

embedded/2024/9/24 17:31:15/

UIWebView

Objective-C 调用 JavaScript

在使用UIWebView时,可以使用stringByEvaluatingJavaScriptFromString:方法来执行JavaScript代码。

示例代码:
NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"returnFunction()"];
NSLog(@"JavaScript返回值: %@", result);

JavaScript 调用 Objective-C

通过自定义URL scheme实现。

使用webView的一个返回BOOL类型的监听网页的代理:shouldStartLoadWithRequest,在JS中,window.location.href = “hhh://callback”
在监听中监听头,然后把后面的string截取出来,用SEL变为函数名,然后调用

当在JavaScript中需要调用Objective-C代码时,可以通过改变window.location来触发Objective-C中的代理方法。

示例代码:

在Objective-C中,你可以在UIWebViewDelegatewebView:shouldStartLoadWithRequest:navigationType:方法中捕获这些请求:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {NSURL *URL = [request URL];if ([[URL scheme] isEqualToString:@"hhh"]) {NSString *functionName = [URL host]; // 获取"callback"SEL selector = NSSelectorFromString([functionName stringByAppendingString:@":"]);if ([self respondsToSelector:selector]) {[self performSelector:selector withObject:nil afterDelay:0];}return NO;}return YES;
}

在JavaScript中,你可以这样触发Objective-C代码:

window.location.href = "hhh://callback";

建议使用更安全的方式

虽然上述方法可行,但自定义URL scheme方法可能导致安全问题,例如,可能会被恶意利用执行未授权的方法。因此,推荐使用更安全和现代的方法如WKWebViewWKScriptMessageHandler进行Native和JavaScript的交互

注意:UIWebView已经被苹果于弃用,使用会造成审核不通过,推荐使用WKWebView


WKWebView

1. JavaScriptCore

JavaScriptCore是一个JavaScript引擎,提供了与JavaScript上下文(context)的接口,可以用来执行JavaScript代码和访问JavaScript对象。JavaScriptCore封装了一些基础的JavaScript对象,如Date、Array等,并允许你定义自己的对象和函数。

原生调用H5

在Objective-C代码中执行你需要的JavaScript代码。

示例代码:

JSContext *context = [[JSContext alloc] init];// 执行JavaScript
[context evaluateScript:@"your javascript code here"];
H5调用原生

在Objective-C中,可以通过context[@"functionName"]来注册一个可以被JavaScript调用的方法。

示例代码:

JSContext *context = [[JSContext alloc] init];// 定义Objective-C block
context[@"log"] = ^(NSString *msg) {NSLog(@"JS: %@", msg);
};

然后在你的JavaScript代码中调用该方法:

log('Hello from JavaScript');

2. evaluateJavaScript和WKScriptMessageHandler

evaluate:评价,评估,估值

evaluateJavaScript:实现原生调用H5

使用WKWebViewevaluateJavaScript方法调用JavaScript代码,并从中获取结果。

示例代码:

在Objective-C中通过WKWebView调用JavaScript:

#import <WebKit/WebKit.h>// 假设self.webView是你的WKWebView实例
WKWebView *webView = [[WKWebView alloc] init];// JavaScript代码字符串
NSString *script = @"document.title";// 执行JavaScript
[webView evaluateJavaScript:script completionHandler:^(id _Nullable result, NSError * _Nullable error) {if (error) {NSLog(@"JavaScript执行错误: %@", error);return;}NSLog(@"页面标题: %@", result);
}];

WKScriptMessageHandler:实现H5调用原生

WKWebView提供了更现代和功能更强大的接口来与JavaScript交互evaluateJavaScript:completionHandler:方法可以执行JavaScript代码,并通过回调接收结果。你也可以使用WKScriptMessageHandler创建一个消息处理器,当JavaScript通过window.webkit.messageHandlers.YourHandler.postMessage(data)发送消息时,你可以在Objective-C的userContentController:didReceiveScriptMessage:方法中接收到。

首先在Objective-C中创建消息处理器:

// 在didFinishNavigation代理方法中添加JS调用OC的方法
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {// 注册一个name为hello的js方法[webView.configuration.userContentController addScriptMessageHandler:self name:@"hello"];
}//实现WKScriptMessageHandler此代理,然后在网页端通过window.webkit.messageHandlers.hello.postMessage({body: 'test'});即可调用
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {NSLog(@"body: %@", message.body);
}

以上就是使用
evaluateJavaScript 来实现原生调用H5
WKScriptMessageHandler 来实现H5调用原生

3. WKWebViewJavascriptBridge

WKWebViewJavascriptBridge是一个流行的开源库,用于在iOS应用中的WKWebView和HTML页面之间进行JavaScript与Objective-C或Swift代码的交互。它提供了一个简化的接口来发送消息和调用函数,使得原生代码和Web代码之间的通信更加便捷。

WKWebViewJavascriptBridge不完全属于之前提到的三种方法,它实际上是基于WKWebViewWKScriptMessageHandler封装而成的一个桥接工具,但它提供了更加高级和易用的API。

示例代码:

首先,项目中安装WKWebViewJavascriptBridge,通常通过CocoaPods安装:

pod 'WKWebViewJavascriptBridge', '~> 1.0.0'

然后,可以在你的Objective-C代码中这样使用它:

#import <WebKit/WebKit.h>
#import "WKWebViewJavascriptBridge.h"@interface ViewController ()@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic, strong) WKWebViewJavascriptBridge *bridge;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// 设置WebViewself.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];[self.view addSubview:self.webView];// 初始化bridgeself.bridge = [WKWebViewJavascriptBridge bridgeForWebView:self.webView];[self.bridge setWebViewDelegate:self];// 注册一个供JS调用的方法[self.bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {NSLog(@"testObjcCallback called: %@", data);responseCallback(@"Response from testObjcCallback");}];// 调用JS的方法[self.bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }];// 加载页面NSURL *url = [NSURL URLWithString:@"https://example.com"];[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
}@end

在你的HTML/JavaScript中,你也需要设置对应的处理函数和调用:

// Connect to the Objective-C bridge
document.addEventListener('DOMContentLoaded', function() {window.WebViewJavascriptBridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {console.log("ObjC called testJavascriptHandler with", data);var responseData = { 'Javascript Says':'Right back atcha!' };responseCallback(responseData);});
});

这样,就设置了一个双向通信的桥,可以从JavaScript调用Objective-C代码,也可以从Objective-C调用JavaScript代码。


http://www.ppmy.cn/embedded/16988.html

相关文章

C++:拷贝构造函数的初始化列表

拷贝构造函数的初始化列表是在拷贝构造函数的定义中出现的一组初始值&#xff0c;用于初始化新创建的对象的成员变量。它的语法是在构造函数的声明后面使用冒号&#xff08;:&#xff09;来开头&#xff0c;然后列出要初始化的成员变量和它们的初始值。初始化列表的优点在于它允…

4、Flink执行模式(流/批)详解(下)

1、执行模式设置 import org.apache.flink.api.common.RuntimeExecutionMode; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;/*** bin/flink run -Dexecution.runtime-modeBATCH <jarFile>*/ public class _01_RuntimeMode {public s…

学习OpenCV——CV_8UC1、CV_16UC1、CV_32FC1等对应的整数值及计算方法(一)

学习OpenCV——CV_8UC1、CV_16UC1、CV_32FC1等对应的整数值及计算方法&#xff08;一&#xff09; 1.代码段2.计算方法举例3.直接给出其余对应结果 1.代码段 以下取自OpenCV文档 #define CV_BIG_INT(n) #define CV_BIG_UINT(n) #define CV_CN_MAX 512 #define CV…

Node.js -- path模块

path.resolve(常用) // 导入fs const fs require(fs); // 写入文件 fs.writeFileSync(_dirname /index.html,love); console.log(_dirname /index.html);// D:\nodeJS\13-path\代码/index.html 我们之前使用的__dirname 路径 输出的结果前面是正斜杠/ &#xff0c;后面部分是…

使用Uiautomotorviewer无法获取手机页面元素+解决办法

在进行 Android 应用程序开发或测试时&#xff0c;有时会遇到以下错误&#xff1a; Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException这个错误可能会导致开发或测试过程中的一些困扰&#xff0c;但有一个简单的解决方法&#xff1a; 解决方法…

【blog项目】layui与jquery冲突导致鼠标悬停事件失效、如何调用layui.use()作用域里的方法

blog项目前台展示——查询数据库中的文章类型并展示时出现的bug 1 正常演示 2 用jquery查询数据库并添加到页面后 3 相关代码 <script src"/static/jquery-2.1.4.js"></script> <script src"/static/layui/layui.js"></script> …

迅雷不限速破解方法

背景&#xff1a;现在迅雷和百度云的下载速度真的太恶心了&#xff0c;所以总有大佬可以采用厉害的方法进行破解&#xff0c;在网上看了一圈&#xff0c;很多都是骗人或者是无效的&#xff0c;找了一个靠谱的方法&#xff0c;亲测速度能达到10M以上&#xff0c;非常给力。 以下…

保姆级银河麒麟V10高级服务器离线安装mysql5.7数据库

离线在银河麒麟高级操作系统v10安装mysql5.7 下载mysql5.7 MySQL :: Download MySQL Community Server (Archived Versions) 2、把下载好的包上传到服务器 3、解压 [root1-0001 ~]# cd /data/mysql[root1-0001 mysql]# tar -zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz…