目录
1. WKWebView
2. UIWebView(javascriptcore.framework)
3. 三方WebViewJavascriptBridge框架
1. WKWebView
:UIView
iOS8后推出
Safari浏览器(iPhone、mac)都是基于WKWebView 实现的。
相比WebView更省内存。
1.1 使用详解
#import <WebKit/WebKit.h>
<WKScriptMessageHandler,WKUIDelegate,WKNavigationDelegate>
/**
初始化UI
*/
-(void)setupUI{
[self.view addSubview:self.webView];
}
/**
设置URL,并加载
*/
-(void)setUrlStr:(NSString *)urlStr{
_urlStr=urlStr;
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]]];
}
-(WKWebView *)webView{
if(!_webView){
// 创建WKWebView
_webView=[[WKWebView alloc]initWithFrame:CGRectZero configuration:({
// 创建配置类
WKWebViewConfiguration *config=[WKWebViewConfiguration new];
config;
})];
[_webView setFrame:CGRectMake(0, C_NavBarAndStatusBarHeight, C_ScreenWidth, C_ScreenHeight-C_NavBarAndStatusBarHeight)];
// 设置dele <WKUIDelegate,WKNavigationDelegate>
[_webView setUIDelegate:self];
[_webView setNavigationDelegate:self];
// 设置其他
[_webView setBackgroundColor:[UIColor whiteColor]];
[_webView.scrollView setShowsVerticalScrollIndicator:false];
[_webView.scrollView setShowsHorizontalScrollIndicator:false];
}
return _webView;
}
常用属性/方法
获取常用信息
// 标题(readOnly)
NSString *title=webView.title;
// url地址(readOnly)
NSURL *URL=webView.URL;
// 是否正在加载(readOnly)
BOOL loading=webView.isLoading
// 加载进度(readOnly)
double estimatedProgress=webView.estimatedProgress;
// 是否加密(readOnly)
BOOL hasOnlySecureContent=webView.hasOnlySecureContent;
// scrollView(readOnly)
UIScrollView *scrollView=webView.scrollView;
加载请求
// loadRequest
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"url"]]];
// 加载fileURL
[webView loadFileURL:[NSURL URLWithString:@""] allowingReadAccessToURL:[NSURL URLWithString:@""]];
// 加载data
[webView loadData:[NSData data] MIMEType:@"" characterEncodingName:@"" baseURL:[NSURL URLWithString:@""]];
// 加载本地html
NSString *urlStr=[[NSBundle mainBundle]pathForResource:@"index.html" ofType:nil];
[webView loadHTMLString:[NSString stringWithContentsOfFile:urlStr encoding:NSUTF8StringEncoding error:nil] baseURL:[NSURL URLWithString:urlStr]];
重新加载
// 重新加载
[webView reload];
// 重新加载初始网址
[webView reloadFromOrigin];
// 停止加载
[webView stopLoading];
预览
// 设置 是否允许预览链接(默认:true)
[webView setAllowsLinkPreview:true];
向前向后
// 设置 是否支持手势前进后退(默认:false)
[webView setAllowsBackForwardNavigationGestures:true];
// 是否允许向后(readOnly)
BOOL canGoBack=webView.canGoBack;
// 是否允许向前(readOnly)
BOOL canGoForward=webView.canGoForward;
// 向后
[webView goBack];
// 向前
[webView goForward];
// 获取页面前进后退列表(readOnly)
WKBackForwardList *list=webView.backForwardList;
// 当前(readOnly)
WKBackForwardListItem *item=list.currentItem;
// 前一个(readOnly)
WKBackForwardListItem *itemForward=list.forwardItem;
// 后一个(readOnly)
WKBackForwardListItem *itemBack=list.backItem;
// 后列表(readOnly)
NSArray *backList=list.backList;
// 前列表(readOnly)
NSArray *forwardList=list.forwardList;
// 根据下标获取指定页
WKBackForwardListItem *item=[list itemAtIndex:0];
// 前进或后退到指定页
[webView goToBackForwardListItem:item];
// (readOnly)
NSURL *URL=item.URL;
NSURL *initialURL=item.initialURL;
NSString *title=item.title;
dele
【OC调用js中的方法】
[webView evaluateJavaScript:@"helloWorld" completionHandler:^(id _Nullable obj, NSError * _Nullable error) {}];
【js调用OC中的方法】
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// 首先设置交互(js调用OC),设置dele
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"helloWorld"];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
// 最后移除交互
[self.webView.configuration.userContentController removeAllUserScripts];
}
#pragma mark dele <WKScriptMessageHandler>
// js调用OC方法后调用(required)
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
NSLog(@"js调用OC方法后调用");
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@:",message.name]);
if ([self respondsToSelector:selector]) {
[self performSelector:selector withObject:message.body];
}
}
// js中这样调用 window.webkit.messageHandlers.helloWorld.postMessage({body: 'hello world!'});
-(void)helloWorld:(NSDictionary *)dic{
NSLog(@"");
}
#pragma mark dele<WKUIDelegate> 都为可选方法
// =============== alert、confirm、prompt
// js中调用alert后调用
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
NSLog(@"js中调用alert");
/*
message:alert中的内容
*/
completionHandler();
}
// js中调用confirm后调用
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
NSLog(@"js中调用confirm");
/*
message:confirm中的内容
*/
// true确认,false取消
completionHandler(true);
}
// js中调用prompt后调用
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
NSLog(@"js中调用prompt");
/*
prompt:标题
defaultText:默认文本
*/
// 文本框中的填写内容
completionHandler(@"你好");
}
// =============== 预览
// 是否允许预览(长安链接时触发预览)
- (BOOL)webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo{
/*
elementInfo.linkURL 预览的url
*/
return true;
}
// 触发预览后调用,返回预览VC
- (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray<id <WKPreviewActionItem>> *)previewActions{
return [UIViewController new];
}
// 触发pop操作预览消失时调用
- (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController{
NSLog(@"预览取消时调用");
}
// =============== 创建/关闭
// 创建新的webView后回调,调用window.open()创建新窗口后触发
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
// 必须使用configuration
return [[WKWebView alloc]initWithFrame:CGRectZero configuration:configuration];
}
// 关闭当前webView后调用,调用window.close()触发
-(void)webViewDidClose:(WKWebView *)webView{
NSLog(@"关闭webView");
}
#pragma mark dele<WKNavigationDelegate> 都为可选方法
// =============== 页面加载
// 页面开始加载时调用
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
NSLog(@"页面开始加载");
}
// 开始加载内容后调用
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
NSLog(@"页面开始加载内容");
}
// 页面加载完成后调用
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
NSLog(@"页面加载完成");
}
// 页面加载失败后调用
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{
NSLog(@"页面加载失败");
}
// 页面加载内容中断时调用
-(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{
NSLog(@"加载内容中断");
}
// =============== 跳转
// 是否允许跳转(发送request请求之前调用)
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
/*
navigationAction.sourceFrame 原 WKFrameInfo(只读)
navigationAction.targetFrame 目标 WKFrameInfo(只读)
navigationAction.request request(只读)
navigationAction.navigationType 请求类型
WKNavigationTypeLinkActivated, // 链接href
WKNavigationTypeFormSubmitted, // 表单提交
WKNavigationTypeBackForward, // 返回
WKNavigationTypeReload, // 重新加载
WKNavigationTypeFormResubmitted,// 表单重复提交
WKNavigationTypeOther = -1, // 其他
WKNavigationActionPolicyAllow 允许
WKNavigationActionPolicyCancel 拒绝
*/
decisionHandler(WKNavigationActionPolicyAllow);
}
// 是否允许跳转(发送request请求并收到响应后)
-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
/*
navigationResponse.forMainFrame 是否是main frame(只读)
navigationResponse.response 获取响应response(只读)
WKNavigationResponsePolicyAllow 允许
WKNavigationResponsePolicyCancel 拒绝
*/
decisionHandler(WKNavigationResponsePolicyAllow);
}
// 重定向后调用(接收到服务器的跳转请求)
-(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
NSLog(@"后端重定向");
}
// 跳转失败后调用
-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{
NSLog(@"跳转失败");
}
// https则调用
-(void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
/*
NSURLSessionAuthChallengeUseCredential, 使用(信任)证书
NSURLSessionAuthChallengePerformDefaultHandling, 默认,忽略
NSURLSessionAuthChallengeCancelAuthenticationChallenge, 取消
NSURLSessionAuthChallengeRejectProtectionSpace, 这次取消,下载次还来问
*/
// challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
completionHandler(NSURLSessionAuthChallengeUseCredential,[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
1.2 其他
WKWebViewConfiguration
// 1.创建配置类
WKWebViewConfiguration *config=[WKWebViewConfiguration new];
// 1.1设置偏好设置
config.preferences=({
WKPreferences *pre=[WKPreferences new];
[pre setMinimumFontSize:10]; // 最小字体(默认:0)
[pre setJavaScriptEnabled:true]; // js是否可用(默认:true)
[pre setJavaScriptCanOpenWindowsAutomatically:false]; // js是否能通过打开窗口 (默认:false)
pre;
});
// 1.2设置内容处理池
config.processPool=[WKProcessPool new];
// 1.3设置交互(js调用OC)
[config setUserContentController:({
WKUserContentController *userC=[WKUserContentController new];
// 添加交互,当收到js调用ssbb后 回调didReceiveScriptMessage <WKScriptMessageHandler>
[userC addScriptMessageHandler:self name:@"ssbb"];
userC;
})];
// ---------- 其他常用属性 start 可选----------
// 设置 持久化
// 一个WKWebsiteDataStore对象代表了被网页使用的各种类型的数据。包括cookies,磁盘文件,内存缓存以及持久化数据如WebSQL,IndexedDB数据库,local storage。
[config setWebsiteDataStore:[WKWebsiteDataStore defaultDataStore]];
// 设置 在web全部加载到内存前是否阻止其显示
[config setSuppressesIncrementalRendering:true];
// 设置 UserAgent中的应用名称
[config setApplicationNameForUserAgent:@""];
// 设置 是否允许AirPlay播放媒体(默认:true)
[config setAllowsInlineMediaPlayback:true];
// 设置 是否忽略缩放属性(默认:false)覆盖网页中的user-scalable HTML属性
[config setIgnoresViewportScaleLimits:true];
// 设置 需要检测的数据类型(可对相应的类型做处理,如链接则可跳转)
[config setDataDetectorTypes:WKDataDetectorTypeLink];
/*
WKDataDetectorTypeNone 不检测(默认)
WKDataDetectorTypePhoneNumber 电话
WKDataDetectorTypeLink 链接
WKDataDetectorTypeAddress 地址
WKDataDetectorTypeCalendarEvent 日历提醒事件
WKDataDetectorTypeTrackingNumber 跟踪号码/查询号/运单号
WKDataDetectorTypeFlightNumber 航班号
WKDataDetectorTypeLookupSuggestion
WKDataDetectorTypeAll 检测所有类型
*/
// 设置 是否允许画中画播放?
[config setAllowsPictureInPictureMediaPlayback:true];
// 设置 选择内容的粒度级别
[config setSelectionGranularity:WKSelectionGranularityDynamic];
/*
WKSelectionGranularityDynamic, 用户可自定义选择区域(默认)
WKSelectionGranularityCharacter, 不可自定义选择区域
*/
// 设置 是否使用在线的控制器(默认:false,使用本地的全屏控制器)
[config setAllowsInlineMediaPlayback:true];
// 设置 哪些视频需要用户手势才能自动播放
[config setMediaTypesRequiringUserActionForPlayback:WKAudiovisualMediaTypeAll];
/*
WKAudiovisualMediaTypeNone 所有视频自动播放
WKAudiovisualMediaTypeAudio 音频
WKAudiovisualMediaTypeVideo 视频
WKAudiovisualMediaTypeAll 所有都需要手势才能播放
*/
//
// ---------- 其他常用属性 end----------
2. UIWebView+原生框架(javascriptcore.framework)
- UIWebView 基础使用
UIWebView : UIView <NSCoding, UIScrollViewDelegate>
// 创建
UIWebView *webV=[UIWebView new];
[self.view addSubview:webV];
加载url
// 方式一:加载 url
[webV loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]];
// 方式二:加载 htmlStr
[webV loadHTMLString:@"<p>hello</p>" baseURL:nil];
// 方式三:加载 nsdata
[webView loadData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"1.docx" ofType:nil]] MIMEType:@"application/vnd.openxmlformats-officedocument.wordprocessingml.document" textEncodingName:@"UTF-8" baseURL:nil];
/*
1.docx
application/vnd.openxmlformats-officedocument.wordprocessingml.document
2.pdf
application/pdf
3.txt
text/plain
4.html
text/html
*/
缓存
// 注意:缓存只影响本地址,页面内其他链接地址不受影响。
NSURLRequest *request=[[NSURLRequest requestWithURL:[NSURL URLWithString:@""] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10]];
/*
NSURLRequestUseProtocolCachePolicy = 0, 默认(使用缓存)
NSURLRequestReloadIgnoringLocalCacheData = 1, 忽略本地缓存
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData, 忽略本地缓存
NSURLRequestReturnCacheDataElseLoad = 2, 返回缓存,缓存没有则请求网络
NSURLRequestReturnCacheDataDontLoad = 3, 返回缓存,缓存没有则出错
NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
*/
dele
// dele<UIWebViewDelegate>
[webV setDelegate:self];
/**
* 是否允许该request请求进行加载(加载前调用)
*
* 1、调用loadRequest等会调用
* 2、调用goBack后会调用(request的缓存策略是NSURLRequestReturnCacheDataElseLoad)
* 3、页面内点击其他链接会调用(request的缓存策略是NSURLRequestUseProtocolCachePolicy)
* 4、重定向会调用
*/
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
return true;
/*
UIWebViewNavigationTypeLinkClicked, 用户触击了一个链接
UIWebViewNavigationTypeFormSubmitted, 用户提交了一个表单
UIWebViewNavigationTypeBackForward, 用户触击前进或返回按钮
UIWebViewNavigationTypeReload, 用户触击重新加载的按钮
UIWebViewNavigationTypeFormResubmitted, 用户重复提交表单
UIWebViewNavigationTypeOther 发生其它行为
*/
}
// 开始加载(网页内容)后调用
- (void)webViewDidStartLoad:(UIWebView *)webView{}
// (网页内容完全显示在控件上)加载完毕后调用
- (void)webViewDidFinishLoad:(UIWebView *)webView{
// 获取web页面内容信息
NSString *docStr=[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.textContent"];
/*
JavaScript的执行时间被限定在10秒钟,如果执行时间超过10秒,那么页面就停止执行这个脚本。
JavaScript的执行可能阻塞主线程,所以当脚本执行的时候不允许用户影响页面的加载。
JavaScript的内存分配被限制在10M,如果超出这个限制那么页面会发生异常。
*/
}
// 加载失败后调用
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{}
前进后退
// 获取 页面数量
NSInteger pageCount=webV.pageCount;
// 是否 可以回退
BOOL isCanBack=[webV canGoBack];
// 是否 可以前进
BOOL isCanForward=[webV canGoForward];
// 回退
[webV goBack];
// 前进
[webV goForward];
重新加载
// 是否 正在加载
BOOL isLoading=[webV isLoading];
// 重新加载(会重新调用shouldStartLoadWithRequest等)
[webV reload];
// 停止加载
[webV stopLoading];
滚动条
// 设置 是否显示纵向滚动条
[webV.scrollView setShowsVerticalScrollIndicator:true];
// 设置 是否显示横向滚动条
[webV.scrollView setShowsHorizontalScrollIndicator:true];
显示
// 是否网页内容下载完毕才开始渲染web视图,默认为NO
@property (nonatomic) BOOL suppressesIncrementalRendering;
// 是否允许长按链接预览(支持3D Touch的设备),default is NO
@property (nonatomic) BOOL allowsLinkPreview;
// 设置是否缩放到适合屏幕大小(默认:false)
[webV setScalesPageToFit:true];
其他
// 设置 是否允许media后台播放
[webV setAllowsInlineMediaPlayback:true];
// 获取scrollView(只读)
UIScrollView *scrollView=webView.scrollView;
// 获取NSURLRequest (只读)
NSURLRequest *request=webView.request;
// 翻页效果(当网页的大小超出view时,将网页以翻页的效果展示)
@property (nonatomic) UIWebPaginationMode paginationMode;
/*
UIWebPaginationModeUnpaginated, // 不使用翻页效果
UIWebPaginationModeLeftToRight, // 将网页超出部分分页,从左向右进行翻页
UIWebPaginationModeTopToBottom, // 将网页超出部分分页,从上向下进行翻页
UIWebPaginationModeBottomToTop, // 将网页超出部分分页,从下向上进行翻页
UIWebPaginationModeRightToLeft // 将网页超出部分分页,从右向左进行翻页
*/
// 分页模式
@property (nonatomic) UIWebPaginationBreakingMode paginationBreakingMode;
/*
UIWebPaginationBreakingModePage,
UIWebPaginationBreakingModeColumn
*/
// 每一页的长度
@property (nonatomic) CGFloat pageLength;
// 每一页的间距
@property (nonatomic) CGFloat gapBetweenPages;
// 是否在弹出键盘后允许用户交互,默认YES
@property (nonatomic) BOOL keyboardDisplayRequiresUserAction;
音视频
// 是否允许分屏播放
@property (nonatomic) BOOL allowsPictureInPictureMediaPlayback;
// 是否使用内嵌HTML5播放视频(还是用本地的全屏控制)。
// 内嵌则HTML中的video元素必须包含webkit-playsinline属性。
// iPhone Safari defaults to NO. iPad Safari defaults to YES
@property (nonatomic) BOOL allowsInlineMediaPlayback;
// 是否允许自动播放,默认为YES
@property (nonatomic) BOOL mediaPlaybackRequiresUserAction;
// 音频播放是否支持air play功能,默认为YES
@property (nonatomic) BOOL mediaPlaybackAllowsAirPlay;
- UIWebView 原生交互
OC中可以直接调用JS方法
JS可通过拦截url间接调用OC
#import <JavaScriptCore/JavaScriptCore.h>
<UIWebViewDelegate>
// 创建UIWebView
UIWebView *webV=[UIWebView new];
[self.view addSubview:webV];
// 布局,,,
//
[webV setScalesPageToFit:true];
// 滚动速度:正常速,默认慢速
[webV.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal];
// loadRequest(加载网页)
[webV loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"url"]]];
dele
// dele
[webV setDelegate:self];
// 加载完成后调用
-(void)webViewDidFinishLoad:(UIWebView *)webView{
》》》》》OC调js
// 初始化一些操作 (如:提交表单,插入内容,删除内容,修改内容,查询内容)
[webView stringByEvaluatingJavaScriptFromString:@"js代码"];
举例:
// 提交表单
[webView stringByEvaluatingJavaScriptFromString:@"document.froms[0].submit();"];
// 插入内容
[webView stringByEvaluatingJavaScriptFromString:@" js 代码"];
// 例:
@"var script=document.createElement('script');" // 可以是普通控件如img(.src .width .height)
@"script.type='text/javascript';"
@"script.text=\"function myFun(){"
@"var f=document.getElementsByName(‘q’)[0];"
@"f.value='11';"
@"document.forms[0].submit();"
@"}\";"
@"document.getElementsByTagName('head')[0].appendChild(script);"
// 删除内容
[webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('a').remove()"];
// 修改内容值、显示值
[webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByName('a')[0].value='123'"];
[webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByName('a')[0].innerHTML='h123'"];
// 查询内容
// url
NSString *urlStr=[webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];
// title : document.title
// 禁用 页面元素选择
[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
// 禁用 长按弹出ActionSheet
[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
》》》》》 js调用OC (方式一,原生JavaScriptCore.framework框架(iOS7))
#import<JavaScriptCore/JavaScriptCore.h>
/* 2种方式:
1、Block:暴露单个方法(不能直接使用JSValue、JSContext,造成循环引用)
2、JSExport协议:暴露单个对象
*/
方式一(Block):
OC代码
#import <JavaScriptCore/JavaScriptCore.h>
// 获取 js代码的执行环境
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// Block (注册)
context[@"js中的函数名"] = ^{
NSArray *arg = [JSContext currentArguments];
};
context[@"js中的函数名"] = ^(NSDictionary *dic){
NSLog(@"函数的实参值:%@", dic[@"color"]);
};
js代码
function testClick(){
var str1=document.getElementById("text1").value;
var str2=document.getElementById("text2").value;
函数名(str1,str2);
}
方式二(<JSExport>):
实现协议遵守<JSExport>,JS中调用时(会将方法转为驼峰式,也可以使用宏JSExportAs(sbAdd,+(void)method:(int)a with:(int)b))此宏只对带参有效
JS中调用:对象.属性 , 对象.方法 (不能在这增加成员变量)
}
// 是否允许加载网络请求
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
》》》》》 js调用OC (方式二,拦截url)
//
NSString *urlStr=request.URL.absoluteString;
//
NSRange range=[urlStr rangeOfString:@"ssbb://"];
if(range.location!=NSNotFound){
NSString *method=[urlStr substringFromIndex:range.location+range.length];
[self performSelector:NSSelectorFromString(method)];
return false;
}
return true;
}
// 开始加载后调用
-(void)webViewDidStartLoad:(UIWebView *)webView{}
// 加载失败后调用
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{}
注意事项
1.JS值的包装
JS中的值拿到OC中是不能直接用的
不能作为OC对象的属性
JSValue *value=[context evalutateScript:@"2+2"]; [value toInt32];
/*
OC type JS type
nil undefined
NSNull null
NSString string
NSNumber number,boolean
NSDictionary Object object
NSArray Array object
NSDate Date Object
NSBlock Function Object
id Wrapper object
Class Constructor object
*/
3. WebViewJavascriptBridge框架(第三方框架)
原理:拦截URL
pod 'WebViewJavascriptBridge'
#import "WebViewJavascriptBridge.h"
// 基于WKWebView,则不用再设置WKWebView 的navigationDelegate(navDele为bridge)
// 基于UIWebView,则不用再设置dele(dele为bridge)
// 0.开启日志调试
[WebViewJavascriptBridge enableLogging];
// 1.创建WKWebView或UIWebView
// 2.创建JavascriptBridge
WebViewJavascriptBridge *_webViewBridge=[WebViewJavascriptBridge bridgeForWebView:webView];
[_webViewBridge setWebViewDelegate:self];
// 2.1配置
// js调OC(注册多个handleName,用于js中调用)
[_webViewBridge registerHandler:@"getUserIdFromOC" handler:^(id data, WVJBResponseCallback responseCallback) {
// data
// callBack
if(responseCallback){
responseCallback(@{@"userId":@"ssbb"});
}
}];
// OC调js
[_webViewBridge callHandler:@"getUserName" data:@{@"name":@"ssbb"} responseCallback:^(id responseData) {
// responseData
}];
~~~~~~~~JS
<script>
/*这段代码固定,必须要放到js中(第一次加载HTML时起作用,目的是加载一次wvjbscheme://__BRIDGE_LOADED__,注册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)
}
/*与OC交互的所有JS方法都要放在此处注册,才能调用通过JS调用OC或者让OC调用这里的JS*/
setupWebViewJavascriptBridge(function(bridge) {
/*注册OC调JS*/
bridge.registerHandler('openWebviewBridgeArticle', function() {
log("openWebviewBridgeArticle was called with by ObjC")
})
/*注册OC调JS*/
bridge.registerHandler('token', function(data, responseCallback) {
log("G星爷: ", data)
responseCallback({这里给我返回拼接后的地址})
})
/* 注册js调OC */
document.getElementById('register').onclick = function () {
bridge.callHandler('ww', {'blogdURL': 'weidsfdl'}, function(response) {
log('JS got response', response)
})
}
})
</script>