UIWebView
Native調(diào)用JS,使用
stringByEvaluatingJavaScriptFromString
來解釋執(zhí)行js腳本织中。
//script即為要執(zhí)行的js方法名稱
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
PS:蘋果推薦iOS8之后的app使用WKWebView
來代替UIWebView,同時(shí)也使用方法evaluateJavaScript:completionHandler:
來替代stringByEvaluatingJavaScriptFromString斩启,因?yàn)闀?huì)一直等待stringByEvaluatingJavaScriptFromString方法執(zhí)行完畢
JS調(diào)用Native米死,需要通過UIWebView
攔截跳轉(zhuǎn)請求并判斷請求頭
是否是協(xié)商好的協(xié)議頭來判斷是否是JS發(fā)起調(diào)用Native的請求倦蚪。
- webView:shouldStartLoadWithRequest:navigationType:
function callNative{
var url = ”callNative://nslogHelloWord“
window.location.href = url;
}
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType{
//callNative 為約定好的協(xié)議頭隘擎,如果是,則頁面不進(jìn)行跳轉(zhuǎn)
if ([request.URL.scheme isEqualToString:@"callNative"]) {
NSlog(@"Hello World");
return NO;
}
//不是自定義協(xié)議頭探孝,跳轉(zhuǎn)頁面
return YES;
}
WKWebView
蘋果自iOS8笋婿、OS X 10.10推薦使用WKWebView
來代替原先的UIWebView
,WKWebView
擁有更快的加載速度和性能顿颅,更低的內(nèi)存占用缸濒,同時(shí)更細(xì)致的代理分類來滿足不同需要的調(diào)用。
Native調(diào)用JS,使用方法evaluateJavaScript:completionHandler:
來解釋執(zhí)行腳本。
//javaScriptString要執(zhí)行的js方法
//completionHandler執(zhí)行結(jié)束回調(diào)或者發(fā)生錯(cuò)誤時(shí)回調(diào)
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *error))completionHandler;
JS調(diào)用Native庇配,通過代理WKScriptMessageHandler來實(shí)現(xiàn)調(diào)用斩跌。
#import "WKWVController.h"
#import <WebKit/WebKit.h>
@interface WKWVController ()<WKUIDelegate,WKScriptMessageHandler>
@property (strong, nonatomic) WKWebView *webView;
@end
@implementation WKWVController
- (void)viewDidLoad {
[super viewDidLoad];
// js配置
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
//監(jiān)聽方法名
[userContentController addScriptMessageHandler:self name:@"jsCallOC"];
// WKWebView的配置
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContentController;
// 顯示W(wǎng)KWebView
_webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds configuration:configuration];
_webView.UIDelegate = self; // 設(shè)置WKUIDelegate代理
[self.view addSubview:_webView];
NSURL *url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[_webView loadRequest:urlRequest];
}
// WKScriptMessageHandler protocol?
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message
{
NSLog(@"方法名:%@", message.name);
NSLog(@"參數(shù):%@", message.body);
// 方法名
NSString *methods = [NSString stringWithFormat:@"%@", message.name];
SEL selector = NSSelectorFromString(methods);
// 調(diào)用方法
if ([self respondsToSelector:selector]) {
[self performSelector:selector withObject:message.body];
} else {
NSLog(@"未實(shí)行方法:%@", methods);
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)jsCallOC{
[self.webView evaluateJavaScript:@"wkNativeCallJS('嘿嘿')" completionHandler:^(id _Nullable data, NSError * _Nullable error) {
NSLog(@"我執(zhí)行完畢");
}];
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>網(wǎng)頁</title>
</head>
<body>
<button onclick="wkWebViewTestClick()" style="height: 100px;width: 200px;">點(diǎn)我調(diào)用native方法</button>
function wkNativeCallJS(info){
//wkwebview 不直接使用js的alert 顯示不了
//http://stackoverflow.com/questions/34185339/wkwebview-javascript-confirm-and-alert-not-working
console.log(info);
}
function wkWebViewTestClick(){
// 復(fù)雜數(shù)據(jù)
var list = [1,2,3];
var dict = {"name":"陽君", "qq":"937447974"};
// JS通知WKWebView,jsCallOC即為在controller中注冊的方法名稱
window.webkit.messageHandlers.jsCallOC.postMessage(dict);
}
</script>
</body>
</html>
JavaScriptCore方式相互調(diào)用
在iOS7.0中蘋果公司增加了JS利器JavaScriptCore
框架捞慌,JavaScriptCore
提供了很多靈活的本地OC與JS的交互方式耀鸦,通過JSContext
和JSValue
來完成的,JSContext
是一個(gè)WebView中js代碼運(yùn)行環(huán)境啸澡,js可以通過JSContext
以block
和通過繼承JSExport
代理袖订,自定義實(shí)現(xiàn)代理方法。
#import "WVController.h"
#import <JavaScriptCore/JavaScriptCore.h>
@protocol JSObjcDelegate <JSExport>
-(void)logInfo:(NSString*)info;
@end
@interface WVController ()<JSObjcDelegate>
@property (weak, nonatomic) IBOutlet UIWebView *wv;
@property (nonatomic, strong) JSContext *jsContext;
@end
@implementation WVController
- (void)viewDidLoad {
[super viewDidLoad];
NSString* path = [[NSBundle mainBundle]pathForResource:@"index" ofType:@"html"];
NSURL* url = [NSURL URLWithString:path];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[self.wv loadRequest:request];
}
//oc調(diào)用js
- (IBAction)callJSMethod:(id)sender {
[self.wv stringByEvaluatingJavaScriptFromString:@"wvNativeCallJS()"];
}
//使用url攔截
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
if ([request.URL.scheme isEqualToString:@"callnative"]) {
NSLog(@"hello world");
return false;
}
return true;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
//獲取上下文對象
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"Objc"] = self;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue;
NSLog(@"異常信息:%@", exceptionValue);
};
//直接使用block方式執(zhí)行oc方法
self.jsContext[@"logHello"] = ^(){
NSLog(@"hello");
};
}
//使用代理接口方式執(zhí)行native方法
-(void)logInfo:(NSString *)info{
NSLog(@"js傳來的參數(shù)%@",info);
JSValue* callback = self.jsContext[@"wvNativeCallJS"];
[callback callWithArguments:nil];
}
@end
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>網(wǎng)頁</title>
</head>
<body>
//1
<button onclick="Objc.logInfo('哈哈')" style="height: 100px;width: 200px;">點(diǎn)我調(diào)用native方法</button>
//2
<!-- <button onclick="logHello()" style="height: 100px;width: 200px;">點(diǎn)我調(diào)用native方法</button>-->
<script type="text/javascript">
function wvNativeCallJS(){
alert("wvController");
}
</script>
</body>
</html>
DEMO:下載Demo
參考: