目錄
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>