分為幾大塊:
- JS 與OC 交互的方式有哪些举塔?
- WKWebView相關(guān)API介紹
- WKWebView加載本地HTML
- 進(jìn)度條顯示(KVO獲取其他屬性,如:title)
- 使用中一些問題
JS 與OC 交互的方式有哪些瞳腌?
1唠梨、在JS 中做一次URL跳轉(zhuǎn)碴萧,然后在OC中攔截跳轉(zhuǎn)棵譬。(這里分為UIWebView 和 WKWebView兩種)显蝌;
2、利用WKWebView 的 MessageHandler(WKWebView 是 iOS8推出的)订咸;
3琅束、利用系統(tǒng)庫 JavaScriptCore 來和UIWebView做相互調(diào)用(JavaScriptCore iOS 7推出的);
4算谈、利用第三方庫WebViewJavascriptBridge;
5料滥、利用第三方cordova庫然眼,以前叫PhoneGap(這是一個庫平臺的庫);
JS_OC
JS與OC交互 - URL攔截
iOS下JS與OC互相調(diào)用(一)--UIWebView 攔截URL
iOS下JS與OC互相調(diào)用(二)--WKWebView 攔截URL
JS與OC交互 - 利用WKWebView的MessageHandler
iOS下JS與OC互相調(diào)用(三)--WKWebView的MessageHandler
JS與OC交互 - UIWebView與系統(tǒng)庫JavaScriptCore
iOS下JS與OC互相調(diào)用(四)--UIWebView與JavaScriptCore
JS與OC交互 - 第三方庫WebViewJavascriptBridge
iOS下JS與OC互相調(diào)用(五)--UIWebView + WebViewJavascriptBridge
iOS下JS與OC互相調(diào)用(六)--WKWebView + WebViewJavascriptBridge
JS與OC交互 - 第三方cordova庫
iOS下JS與OC互相調(diào)用(七)--Cordova 基礎(chǔ)
iOS下JS與OC互相調(diào)用(八)--Cordova詳解+實(shí)戰(zhàn)
WKWebView相關(guān)API介紹
WKWebView
@interface WKWebView : UIView
Starting in iOS 8.0 and OS X 10.10, use WKWebView to add web content to your app. Do not use UIWebView or WebView.
// 初始化webview相關(guān)API
// 拷貝一個configuration來初始化一個網(wǎng)頁使用葵腹。它是一個屬性的集合高每,這個集合用來初始化網(wǎng)頁屿岂。
@property(nonatomic, readonly, copy) WKWebViewConfiguration *configuration;
// 初始化一個網(wǎng)頁視圖,設(shè)置其大小和配置
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration;
// 從解檔數(shù)據(jù)獲取一個初始化的對象。
- (nullable instancetype)initWithCoder:(NSCoder *)coder;
// 查看webview信息相關(guān)API
// WKWebView繼承自UIView, 所以如果想設(shè)置scrollView的一些屬性, 需要對此屬性進(jìn)行配置
@property (nonatomic, readonly, strong) UIScrollView *scrollView;
// 頁面標(biāo)題, 一般使用KVO動態(tài)獲取
@property (nullable, nonatomic, readonly, copy) NSString *title;
// 當(dāng)前請求的URL,支持KVO的
@property (nullable, nonatomic, readonly, copy) NSURL *URL;
// 自定義UserAgent, 會覆蓋默認(rèn)的值 API_AVAILABLE(macosx(10.11), ios(9.0))
@property (nullable, nonatomic, copy) NSString *customUserAgent;
// 當(dāng)前提交的導(dǎo)航的SecTrustRef對象倡鲸,支持KVO踩窖。 API_AVAILABLE(macosx(10.12), ios(10.0))
@property (nonatomic, readonly, nullable) SecTrustRef serverTrust;
// 兩個delegaete
// The web view's navigation delegate.
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;
// The web view's user interface delegate.
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;
// 加載content相關(guān)API
// 頁面加載進(jìn)度, 一般使用KVO動態(tài)獲取
@property (nonatomic, readonly) double estimatedProgress;
// 標(biāo)識頁面中的所有資源是否通過安全加密連接來加載,支持KVO的
@property (nonatomic, readonly) BOOL hasOnlySecureContent;
// 當(dāng)前是否在加載內(nèi)容
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
// 重新加載當(dāng)前頁面剖膳。
- (nullable WKNavigation *)reload;
// 重新加載當(dāng)前頁面,如果可能,使用緩存驗(yàn)證條件執(zhí)行端到端重新驗(yàn)證吁朦。
- (nullable WKNavigation *)reloadFromOrigin;
// 停止加載當(dāng)前頁面上的所有資源。
- (void)stopLoading;
// 加載請求API
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
// 加載URL API_AVAILABLE(macosx(10.11), ios(9.0))
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL;
// 直接加載HTML
- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
// 直接加載data API_AVAILABLE(macosx(10.11), ios(9.0))
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL;
// Scaling Content 縮放相關(guān)API
#if !TARGET_OS_IPHONE
// 標(biāo)識是否支持放大手勢渡贾,默認(rèn)為NO
@property (nonatomic) BOOL allowsMagnification;
// 放大因子逗宜,默認(rèn)為1
@property (nonatomic) CGFloat magnification;
// 根據(jù)設(shè)置的縮放因子來縮放頁面,并居中顯示結(jié)果在指定的點(diǎn)
- (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point;
#endif
// 導(dǎo)航相關(guān)API
// 標(biāo)識是否支持左空骚、右swipe手勢是否可以前進(jìn)纺讲、后退
@property (nonatomic) BOOL allowsBackForwardNavigationGestures;
// 是個WKBackForwardList對象,記錄網(wǎng)頁中跳轉(zhuǎn)的記錄
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
// 是否可以招待goback操作囤屹,它是支持KVO的
@property (nonatomic, readonly) BOOL canGoBack;
// 是否可以執(zhí)行g(shù)ofarward操作熬甚,支持KVO
@property (nonatomic, readonly) BOOL canGoForward;
// 返回上一頁面,如果不能返回牺丙,則什么也不干
- (nullable WKNavigation *)goBack;
// 進(jìn)入下一頁面则涯,如果不能前進(jìn),則什么也不干
- (nullable WKNavigation *)goForward;
/* 前進(jìn)/后退到一個指定的記錄上
item必須是WebView的WKBackForwardList中的一個記錄
返回一個新的WKNavigation對象
如果已經(jīng)在當(dāng)前記錄冲簿,或者沒有找到粟判,則會返回nil
*/
- (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
/* API_AVAILABLE(macosx(10.11), ios(9.0))
在iOS上,這個屬性只在支持3D Touch的設(shè)備上支持
在iOS 10及以后的系統(tǒng)版本默認(rèn)值是YES峦剔,之前的默認(rèn)值是NO
如果將該屬性的值設(shè)置為YES档礁,則iOS用戶可以按下鏈接來預(yù)覽鏈接,并可以檢測到地址和電話號碼等數(shù)據(jù)吝沫。這樣的預(yù)覽被用戶稱為peeks
如果用戶在鏈接預(yù)覽上更深入地按下呻澜,預(yù)覽將pop到目標(biāo)網(wǎng)址。該動作會將應(yīng)用程序切換到Safari
如果您想在iOS中支持鏈接預(yù)覽惨险,但又想要在應(yīng)用程序中保留用戶羹幸,那么您可以將WKWebView類轉(zhuǎn)換為SFSafariViewController類
如果您使用WebView作為應(yīng)用內(nèi)瀏覽器,那么進(jìn)行這種更改是最佳選擇
SFSafariViewController自動支持鏈接預(yù)覽
iOS 10.0+開始支持自定義鏈接預(yù)覽辫愉,你也可以通過這種方式來實(shí)現(xiàn)用戶預(yù)覽網(wǎng)頁并pop后仍然留在應(yīng)用內(nèi)而不用切換到Safari栅受,只是你需要做一些額外的適配工作
*/
@property (nonatomic) BOOL allowsLinkPreview;
// 執(zhí)行JavaScript
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
// 截屏
#if TARGET_OS_IPHONE
- (void)takeSnapshotWithConfiguration:(nullable WKSnapshotConfiguration *)snapshotConfiguration completionHandler:(void (^)(UIImage * _Nullable snapshotImage, NSError * _Nullable error))completionHandler API_AVAILABLE(ios(11.0));
WKWebViewConfiguration
WKWebViewConfiguration
只會在webview第一次初始化的時候使用,你不能用此類來改變一個已經(jīng)初始化完成的webview的配置。
// OC與JS交互使用屏镊,通過此屬性來執(zhí)行JavaScript代碼來修改頁面的行為
@property (nonatomic, strong) WKUserContentController *userContentController;
//***********下面屬性一般不需要設(shè)置
// 首選項(xiàng)設(shè)置,
//可設(shè)置最小字號, 是否允許執(zhí)行js
//是否通過js自動打開新的窗口
@property (nonatomic, strong) WKPreferences *preferences;
// 是否允許播放媒體文件
@property (nonatomic) BOOL allowsAirPlayForMediaPlayback
// 需要用戶來操作才能播放的多媒體類型
@property (nonatomic) WKAudiovisualMediaTypes mediaTypesRequiringUserActionForPlayback
// 是使用h5的視頻播放器在線播放, 還是使用原生播放器全屏播放
@property (nonatomic) BOOL allowsInlineMediaPlayback;
......
WKUserContentController
WKUserContentController
是JavaScript
與原生進(jìn)行交互的橋梁, 主要使用的方法有:
// 注入JavaScript與原生交互協(xié)議
// JS 端可通過 window.webkit.messageHandlers.<name>.postMessage(<messageBody>) 發(fā)送消息
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
// 移除注入的協(xié)議, 在deinit方法中調(diào)用
- (void)removeScriptMessageHandlerForName:(NSString *)name;
// 通過WKUserScript注入需要執(zhí)行的JavaScript代碼
- (void)addUserScript:(WKUserScript *)userScript;
// 移除所有注入的JavaScript代碼
- (void)removeAllUserScripts;
......
使用WKUserContentController
注入的交互協(xié)議, 需要遵循WKScriptMessageHandler
協(xié)議, 在其協(xié)議方法中獲取JavaScript
端傳遞的事件和參數(shù):
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
WKScriptMessage
包含了傳遞的協(xié)議名稱及參數(shù), 主要從下面的屬性中獲取:
// 協(xié)議名稱, 即上面的add方法傳遞的name
@property (nonatomic, readonly, copy) NSString *name;
// 傳遞的參數(shù)
@property (nonatomic, readonly, copy) id body;
// 發(fā)送消息的webView
@property (nullable, nonatomic, readonly, weak) WKWebView *webView;
//發(fā)送消息的幀
@property (nonatomic, readonly, copy) WKFrameInfo *frameInfo;
WKPreferences
// webView的偏好設(shè)置
// minimum font size in points default is 0;
@property (nonatomic) CGFloat minimumFontSize;
// 是否啟用javaScript default value is YES.
@property (nonatomic) BOOL javaScriptEnabled;
// 不通過用戶交互依疼,是否可以打開窗口
// default NO in iOS and YES in OS X.
@property (nonatomic) BOOL javaScriptCanOpenWindowsAutomatically;
.......
WKNavigationDelegate
// 當(dāng)WevView的內(nèi)容開始加載時觸發(fā)
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
// 當(dāng)頁面加載內(nèi)容過程中發(fā)生錯誤時觸發(fā)
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
// 當(dāng)WebView開始接收網(wǎng)頁內(nèi)容時觸發(fā)
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
// 當(dāng)前頁面加載完成后觸發(fā)
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
// 頁面發(fā)生錯誤時觸發(fā)
-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error;
// 當(dāng)WebContent進(jìn)程中止時觸發(fā)
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView;
/* 決定是否允許或者取消一次頁面加載請求
WKNavigationAction描述了觸發(fā)本次請求的行為
decisionHandler block在app已經(jīng)決定允許或取消頁面請求時調(diào)用
這個block攜帶一個參數(shù),是WKNavigationActionPolicy枚舉類型
WKNavigationActionPolicy枚舉包括WKNavigationActionPolicyCancel取消和WKNavigationActionPolicyAllow允許兩個枚舉值
你可以立即調(diào)用該block或者保存block并在以后的時間異步調(diào)用它
*/
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
/* 在已經(jīng)收到response時決定是否允許或者取消頁面的加載
WKNavigationResponse描述了response的信息
decisionHandler block在app已經(jīng)決定允許或取消頁面加載時調(diào)用
這個block攜帶一個參數(shù)而芥,是WKNavigationResponsePolicy枚舉類型
WKNavigationResponsePolicy枚舉類型包括WKNavigationResponsePolicyCancel取消和WKNavigationResponsePolicyAllow允許兩個枚舉值
你可以立即調(diào)用該block或者保存block并在以后的時間異步調(diào)用它律罢。
*/
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
// 當(dāng)WebView需要響應(yīng)網(wǎng)頁的登錄請求時觸發(fā)
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;
WKUIDelegate
// 創(chuàng)建新的webview
// 可以指定配置對象、導(dǎo)航動作對象棍丐、window特性
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
// webview關(guān)閉時回調(diào)
- (void)webViewDidClose:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0);
// 調(diào)用JS的alert()方法
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
// 調(diào)用JS的confirm()方法
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
// 調(diào)用JS的prompt()方法
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;
WKWebView加載本地HTML
iOS中wkwebview加載本地html的要點(diǎn)
iOS之在webView中引入本地html,image,js,css文件的方法
方法一:WKWebView加載網(wǎng)頁方法:loadRequest:
本地HTML路徑獲取方式有兩種:pathForResource
和 URLForResource
NSString * localurl_1 = [[NSBundle mainBundle] pathForResource:@"error" ofType:@"html"];
NSURLRequest *request = [NSURLRequest requestWithURL:[[NSURL alloc] initWithString:localurl_1]];
[_wkWebView loadRequest:request];
NSURL * localurl = [[NSBundle mainBundle] URLForResource:@"error" withExtension:@"html"];
NSURLRequest *request = [NSURLRequest requestWithURL:localurl];
[_wkWebView loadRequest:request];
WKWebView加載后發(fā)現(xiàn) pathForResource
加載失敗误辑,可以看出:
1、pathForResource 的結(jié)果是純路徑
2骄酗、URLForResource 的結(jié)果是加file協(xié)議的路徑
方法二:WKWebView加載網(wǎng)頁方法:loadHTMLString: baseURL:
這種方式就是使用pathForResource
來獲取路徑
NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil];
NSString *localHtml = [NSString stringWithContentsOfFile:urlStr encoding:NSUTF8StringEncoding error:nil];
NSURL *fileURL = [NSURL fileURLWithPath:urlStr];
[_wkWebView loadHTMLString:localHtml baseURL:fileURL];
進(jìn)度條顯示(順帶獲取title)
在適當(dāng)?shù)奈恢锰砑覭VO觀察者稀余,離開時要移除
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// KVO 觀察WebView 進(jìn)度條 和 title
[_wkWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
[_wkWebView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
}
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// 移除觀察者
[_wkWebView removeObserver:self forKeyPath:@"estimatedProgress"];
[_wkWebView removeObserver:self forKeyPath:@"title"];
}
創(chuàng)建進(jìn)度條
// Progress 進(jìn)度條
_progressView = [[UIProgressView alloc] init];
_progressView.tintColor = [UIColor greenColor];
_progressView.trackTintColor = [UIColor clearColor];
[self.view addSubview:_progressView];
在KVO回調(diào)中修改頁面
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"estimatedProgress"]) {
if ([change[@"new"] floatValue] < [change[@"old"] floatValue]) {
return;
}
if ([change[@"new"] floatValue] == 1.0) {
[_progressView setProgress:1.0 animated:YES];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_progressView.hidden = YES;
[_progressView setProgress:0 animated:NO];
});
} else {
_progressView.hidden = NO;
[_progressView setProgress:[change[@"new"] floatValue] animated:YES];
}
} else if ([keyPath isEqualToString:@"title"]){
self.title = change[@"new"];
}
}
日常使用中的一些問題
1、wkwebview中 h5絕對布局不生效
//新特性趋翻,解決偏移的問題
if (@available(iOS 11.0, *)) {
_wkWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
然后:前端需要在meta標(biāo)簽中增加 iPhoneX的適配---適配方案viewport-fit:cover
2睛琳、iOS 12中WKWebView中表單 鍵盤彈起自動上移,導(dǎo)致的兼容問題
WKWebView會自動監(jiān)聽鍵盤彈出踏烙,并做上下移動處理(效果如同IQKeyboardManage這些庫)师骗,但是在iOS12中會有一些問題,鍵盤收起后讨惩,控件不恢復(fù)原狀辟癌,或者部分控件消失等不兼容問題
解決方案:
// iOS 12中WKWebView中表單 鍵盤彈起自動上移,但鍵盤下移webview不恢復(fù)
if (@available(iOS 12.0, *)) {
_wkWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic;
}
參考文檔
簡介
WKWebView詳解
WKWebViewTips
[iOS]WKWebView的使用--API篇
WKWebView淺析
WKWebView代理方法解析
使用中的問題
iOS 11 WKWebView新特性
iOS WKWebView無法處理URL Scheme和App Store鏈接的問題解決
WKWebView使用過程中遇到的坑
iOS中UIWebView與WKWebView荐捻、JavaScript與OC交互黍少、Cookie管理看我就夠(上)
iOS中UIWebView與WKWebView、JavaScript與OC交互处面、Cookie管理看我就夠(中)
iOS中UIWebView與WKWebView厂置、JavaScript與OC交互、Cookie管理看我就夠(下)